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

Side by Side Diff: pkg/front_end/lib/src/fasta/parser/parser.dart

Issue 2804753003: Parse type substitution comments /*=T*/ in variable declarations with Fasta. (Closed)
Patch Set: Move generic comment 'inject' methods to Listener. Created 3 years, 8 months 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
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 fasta.parser.parser; 5 library fasta.parser.parser;
6 6
7 import '../fasta_codes.dart' 7 import '../fasta_codes.dart'
8 show 8 show
9 FastaCode, 9 FastaCode,
10 FastaMessage, 10 FastaMessage,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 58
59 import '../scanner/recover.dart' show closeBraceFor, skipToEof; 59 import '../scanner/recover.dart' show closeBraceFor, skipToEof;
60 60
61 import '../scanner/keyword.dart' show Keyword; 61 import '../scanner/keyword.dart' show Keyword;
62 62
63 import '../scanner/precedence.dart' 63 import '../scanner/precedence.dart'
64 show 64 show
65 ASSIGNMENT_PRECEDENCE, 65 ASSIGNMENT_PRECEDENCE,
66 AS_INFO, 66 AS_INFO,
67 CASCADE_PRECEDENCE, 67 CASCADE_PRECEDENCE,
68 EOF_INFO,
69 EQUALITY_PRECEDENCE, 68 EQUALITY_PRECEDENCE,
70 GENERIC_METHOD_TYPE_ASSIGN,
71 GENERIC_METHOD_TYPE_LIST,
72 GT_INFO, 69 GT_INFO,
73 IS_INFO, 70 IS_INFO,
74 MINUS_MINUS_INFO, 71 MINUS_MINUS_INFO,
75 OPEN_PAREN_INFO, 72 OPEN_PAREN_INFO,
76 OPEN_SQUARE_BRACKET_INFO, 73 OPEN_SQUARE_BRACKET_INFO,
77 PERIOD_INFO, 74 PERIOD_INFO,
78 PLUS_PLUS_INFO, 75 PLUS_PLUS_INFO,
79 POSTFIX_PRECEDENCE, 76 POSTFIX_PRECEDENCE,
80 PrecedenceInfo, 77 PrecedenceInfo,
81 QUESTION_INFO, 78 QUESTION_INFO,
82 QUESTION_PERIOD_INFO, 79 QUESTION_PERIOD_INFO,
83 RELATIONAL_PRECEDENCE, 80 RELATIONAL_PRECEDENCE,
84 SCRIPT_INFO; 81 SCRIPT_INFO;
85 82
86 import '../scanner/token.dart' 83 import '../scanner/token.dart'
87 show 84 show
88 BeginGroupToken, 85 BeginGroupToken,
89 CommentToken,
90 KeywordToken, 86 KeywordToken,
91 SymbolToken, 87 SymbolToken,
92 Token, 88 Token,
93 isUserDefinableOperator; 89 isUserDefinableOperator;
94 90
95 import '../scanner/token_constants.dart' 91 import '../scanner/token_constants.dart'
96 show 92 show
97 COMMA_TOKEN, 93 COMMA_TOKEN,
98 DOUBLE_TOKEN, 94 DOUBLE_TOKEN,
99 EOF_TOKEN, 95 EOF_TOKEN,
(...skipping 10 matching lines...) Expand all
110 OPEN_CURLY_BRACKET_TOKEN, 106 OPEN_CURLY_BRACKET_TOKEN,
111 OPEN_PAREN_TOKEN, 107 OPEN_PAREN_TOKEN,
112 OPEN_SQUARE_BRACKET_TOKEN, 108 OPEN_SQUARE_BRACKET_TOKEN,
113 PERIOD_TOKEN, 109 PERIOD_TOKEN,
114 SEMICOLON_TOKEN, 110 SEMICOLON_TOKEN,
115 STRING_INTERPOLATION_IDENTIFIER_TOKEN, 111 STRING_INTERPOLATION_IDENTIFIER_TOKEN,
116 STRING_INTERPOLATION_TOKEN, 112 STRING_INTERPOLATION_TOKEN,
117 STRING_TOKEN; 113 STRING_TOKEN;
118 114
119 import '../scanner/characters.dart' show $CLOSE_CURLY_BRACKET; 115 import '../scanner/characters.dart' show $CLOSE_CURLY_BRACKET;
120 import '../scanner/string_scanner.dart';
121 116
122 import '../util/link.dart' show Link; 117 import '../util/link.dart' show Link;
123 118
124 import 'async_modifier.dart' show AsyncModifier; 119 import 'async_modifier.dart' show AsyncModifier;
125 120
126 import 'listener.dart' show Listener; 121 import 'listener.dart' show Listener;
127 122
128 import 'identifier_context.dart' show IdentifierContext; 123 import 'identifier_context.dart' show IdentifierContext;
129 124
130 /// Returns true if [token] is the symbol or keyword [value]. 125 /// Returns true if [token] is the symbol or keyword [value].
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 /// 177 ///
183 /// Historically, we over-used identical, and when identical is used on other 178 /// Historically, we over-used identical, and when identical is used on other
184 /// objects than strings, it can often be replaced by `==`. 179 /// objects than strings, it can often be replaced by `==`.
185 class Parser { 180 class Parser {
186 final Listener listener; 181 final Listener listener;
187 182
188 Uri get uri => listener.uri; 183 Uri get uri => listener.uri;
189 184
190 bool mayParseFunctionExpressions = true; 185 bool mayParseFunctionExpressions = true;
191 186
192 bool parseGenericMethodComments = false;
193
194 /// Represents parser state: what asynchronous syntax is allowed in the 187 /// Represents parser state: what asynchronous syntax is allowed in the
195 /// function being currently parsed. In rare situations, this can be set by 188 /// function being currently parsed. In rare situations, this can be set by
196 /// external clients, for example, to parse an expression outside a function. 189 /// external clients, for example, to parse an expression outside a function.
197 AsyncModifier asyncState = AsyncModifier.Sync; 190 AsyncModifier asyncState = AsyncModifier.Sync;
198 191
199 Parser(this.listener); 192 Parser(this.listener);
200 193
201 bool get inGenerator { 194 bool get inGenerator {
202 return asyncState == AsyncModifier.AsyncStar || 195 return asyncState == AsyncModifier.AsyncStar ||
203 asyncState == AsyncModifier.SyncStar; 196 asyncState == AsyncModifier.SyncStar;
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after
633 token = expect('.', token.next); 626 token = expect('.', token.next);
634 nameToken = token; 627 nameToken = token;
635 token = parseIdentifier(token, IdentifierContext.fieldInitializer); 628 token = parseIdentifier(token, IdentifierContext.fieldInitializer);
636 } else { 629 } else {
637 nameToken = token; 630 nameToken = token;
638 token = parseIdentifier( 631 token = parseIdentifier(
639 token, IdentifierContext.formalParameterDeclaration); 632 token, IdentifierContext.formalParameterDeclaration);
640 } 633 }
641 } 634 }
642 635
643 token = _injectGenericCommentTypeList(token); 636 token = listener.injectGenericCommentTypeList(token);
644 if (optional('(', token)) { 637 if (optional('(', token)) {
645 Token inlineFunctionTypeStart = token; 638 Token inlineFunctionTypeStart = token;
646 listener.beginFunctionTypedFormalParameter(token); 639 listener.beginFunctionTypedFormalParameter(token);
647 listener.handleNoTypeVariables(token); 640 listener.handleNoTypeVariables(token);
648 token = parseFormalParameters(token); 641 token = parseFormalParameters(token);
649 listener.endFunctionTypedFormalParameter( 642 listener.endFunctionTypedFormalParameter(
650 covariantKeyword, thisKeyword, kind); 643 covariantKeyword, thisKeyword, kind);
651 // Generalized function types don't allow inline function types. 644 // Generalized function types don't allow inline function types.
652 // The following isn't allowed: 645 // The following isn't allowed:
653 // int Function(int bar(String x)). 646 // int Function(int bar(String x)).
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
719 } else { 712 } else {
720 return expect(']', token); 713 return expect(']', token);
721 } 714 }
722 } 715 }
723 716
724 Token parseTypeOpt(Token token) { 717 Token parseTypeOpt(Token token) {
725 if (isGeneralizedFunctionType(token)) { 718 if (isGeneralizedFunctionType(token)) {
726 // Function type without return type. 719 // Function type without return type.
727 return parseType(token); 720 return parseType(token);
728 } 721 }
722 token = listener.injectGenericCommentTypeAssign(token);
729 Token peek = peekAfterIfType(token); 723 Token peek = peekAfterIfType(token);
730 if (peek != null && (peek.isIdentifier() || optional('this', peek))) { 724 if (peek != null && (peek.isIdentifier() || optional('this', peek))) {
731 return parseType(token); 725 return parseType(token);
732 } 726 }
733 listener.handleNoType(token); 727 listener.handleNoType(token);
734 return token; 728 return token;
735 } 729 }
736 730
737 bool isValidTypeReference(Token token) { 731 bool isValidTypeReference(Token token) {
738 final kind = token.kind; 732 final kind = token.kind;
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after
1111 token, 1105 token,
1112 (t) => listener.beginTypeVariables(t), 1106 (t) => listener.beginTypeVariables(t),
1113 (t) => parseTypeVariable(t), 1107 (t) => parseTypeVariable(t),
1114 (c, bt, et) => listener.endTypeVariables(c, bt, et), 1108 (c, bt, et) => listener.endTypeVariables(c, bt, et),
1115 (t) => listener.handleNoTypeVariables(t)); 1109 (t) => listener.handleNoTypeVariables(t));
1116 } 1110 }
1117 1111
1118 /// TODO(ahe): Clean this up. 1112 /// TODO(ahe): Clean this up.
1119 Token parseStuff(Token token, Function beginStuff, Function stuffParser, 1113 Token parseStuff(Token token, Function beginStuff, Function stuffParser,
1120 Function endStuff, Function handleNoStuff) { 1114 Function endStuff, Function handleNoStuff) {
1121 token = _injectGenericCommentTypeList(token); 1115 token = listener.injectGenericCommentTypeList(token);
1122 if (optional('<', token)) { 1116 if (optional('<', token)) {
1123 Token begin = token; 1117 Token begin = token;
1124 beginStuff(begin); 1118 beginStuff(begin);
1125 int count = 0; 1119 int count = 0;
1126 do { 1120 do {
1127 token = stuffParser(token.next); 1121 token = stuffParser(token.next);
1128 ++count; 1122 ++count;
1129 } while (optional(',', token)); 1123 } while (optional(',', token));
1130 Token next = token.next; 1124 Token next = token.next;
1131 if (identical(token.stringValue, '>>')) { 1125 if (identical(token.stringValue, '>>')) {
(...skipping 1266 matching lines...) Expand 10 before | Expand all | Expand 10 after
2398 } 2392 }
2399 2393
2400 Token parseExpressionStatementOrDeclaration(Token token) { 2394 Token parseExpressionStatementOrDeclaration(Token token) {
2401 if (!inPlainSync && optional("await", token)) { 2395 if (!inPlainSync && optional("await", token)) {
2402 return parseExpressionStatement(token); 2396 return parseExpressionStatement(token);
2403 } 2397 }
2404 assert(token.isIdentifier() || identical(token.stringValue, 'void')); 2398 assert(token.isIdentifier() || identical(token.stringValue, 'void'));
2405 Token identifier = peekIdentifierAfterType(token); 2399 Token identifier = peekIdentifierAfterType(token);
2406 if (identifier != null) { 2400 if (identifier != null) {
2407 assert(identifier.isIdentifier()); 2401 assert(identifier.isIdentifier());
2402
2403 // If the identifier token has a type substitution comment /*=T*/,
2404 // then the set of tokens type tokens should be replaced with the
2405 // tokens parsed from the comment.
2406 token =
2407 listener.replaceTokenWithGenericCommentTypeAssign(token, identifier);
2408
2408 Token afterId = identifier.next; 2409 Token afterId = identifier.next;
2409 int afterIdKind = afterId.kind; 2410 int afterIdKind = afterId.kind;
2410 if (identical(afterIdKind, EQ_TOKEN) || 2411 if (identical(afterIdKind, EQ_TOKEN) ||
2411 identical(afterIdKind, SEMICOLON_TOKEN) || 2412 identical(afterIdKind, SEMICOLON_TOKEN) ||
2412 identical(afterIdKind, COMMA_TOKEN)) { 2413 identical(afterIdKind, COMMA_TOKEN)) {
2413 // We are looking at "type identifier" followed by '=', ';', ','. 2414 // We are looking at "type identifier" followed by '=', ';', ','.
2414 return parseVariablesDeclaration(token); 2415 return parseVariablesDeclaration(token);
2415 } else if (identical(afterIdKind, OPEN_PAREN_TOKEN)) { 2416 } else if (identical(afterIdKind, OPEN_PAREN_TOKEN)) {
2416 // We are looking at "type identifier '('". 2417 // We are looking at "type identifier '('".
2417 BeginGroupToken beginParen = afterId; 2418 BeginGroupToken beginParen = afterId;
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
2482 } 2483 }
2483 } 2484 }
2484 return parseExpressionStatement(token); 2485 return parseExpressionStatement(token);
2485 } 2486 }
2486 2487
2487 Token parseExpressionStatementOrConstDeclaration(Token token) { 2488 Token parseExpressionStatementOrConstDeclaration(Token token) {
2488 assert(identical(token.stringValue, 'const')); 2489 assert(identical(token.stringValue, 'const'));
2489 if (isModifier(token.next)) { 2490 if (isModifier(token.next)) {
2490 return parseVariablesDeclaration(token); 2491 return parseVariablesDeclaration(token);
2491 } 2492 }
2493 listener.injectGenericCommentTypeAssign(token.next);
2492 Token identifier = peekIdentifierAfterOptionalType(token.next); 2494 Token identifier = peekIdentifierAfterOptionalType(token.next);
2493 if (identifier != null) { 2495 if (identifier != null) {
2494 assert(identifier.isIdentifier()); 2496 assert(identifier.isIdentifier());
2495 Token afterId = identifier.next; 2497 Token afterId = identifier.next;
2496 int afterIdKind = afterId.kind; 2498 int afterIdKind = afterId.kind;
2497 if (identical(afterIdKind, EQ_TOKEN) || 2499 if (identical(afterIdKind, EQ_TOKEN) ||
2498 identical(afterIdKind, SEMICOLON_TOKEN) || 2500 identical(afterIdKind, SEMICOLON_TOKEN) ||
2499 identical(afterIdKind, COMMA_TOKEN)) { 2501 identical(afterIdKind, COMMA_TOKEN)) {
2500 // We are looking at "const type identifier" followed by '=', ';', or 2502 // We are looking at "const type identifier" followed by '=', ';', or
2501 // ','. 2503 // ','.
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
2790 token = parseArguments(token); 2792 token = parseArguments(token);
2791 listener.endSend(beginToken, token); 2793 listener.endSend(beginToken, token);
2792 } else { 2794 } else {
2793 break; 2795 break;
2794 } 2796 }
2795 } 2797 }
2796 return token; 2798 return token;
2797 } 2799 }
2798 2800
2799 Token parsePrimary(Token token, IdentifierContext context) { 2801 Token parsePrimary(Token token, IdentifierContext context) {
2800 token = _injectGenericCommentTypeList(token); 2802 token = listener.injectGenericCommentTypeList(token);
2801 final kind = token.kind; 2803 final kind = token.kind;
2802 if (kind == IDENTIFIER_TOKEN) { 2804 if (kind == IDENTIFIER_TOKEN) {
2803 return parseSendOrFunctionLiteral(token, context); 2805 return parseSendOrFunctionLiteral(token, context);
2804 } else if (kind == INT_TOKEN || kind == HEXADECIMAL_TOKEN) { 2806 } else if (kind == INT_TOKEN || kind == HEXADECIMAL_TOKEN) {
2805 return parseLiteralInt(token); 2807 return parseLiteralInt(token);
2806 } else if (kind == DOUBLE_TOKEN) { 2808 } else if (kind == DOUBLE_TOKEN) {
2807 return parseLiteralDouble(token); 2809 return parseLiteralDouble(token);
2808 } else if (kind == STRING_TOKEN) { 2810 } else if (kind == STRING_TOKEN) {
2809 return parseLiteralString(token); 2811 return parseLiteralString(token);
2810 } else if (kind == HASH_TOKEN) { 2812 } else if (kind == HASH_TOKEN) {
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
3083 listener.beginNewExpression(newKeyword); 3085 listener.beginNewExpression(newKeyword);
3084 token = parseConstructorReference(token); 3086 token = parseConstructorReference(token);
3085 token = parseRequiredArguments(token); 3087 token = parseRequiredArguments(token);
3086 listener.endNewExpression(newKeyword); 3088 listener.endNewExpression(newKeyword);
3087 return token; 3089 return token;
3088 } 3090 }
3089 3091
3090 Token parseConstExpression(Token token) { 3092 Token parseConstExpression(Token token) {
3091 Token constKeyword = token; 3093 Token constKeyword = token;
3092 token = expect('const', token); 3094 token = expect('const', token);
3093 token = _injectGenericCommentTypeList(token); 3095 token = listener.injectGenericCommentTypeList(token);
3094 final String value = token.stringValue; 3096 final String value = token.stringValue;
3095 if ((identical(value, '[')) || (identical(value, '[]'))) { 3097 if ((identical(value, '[')) || (identical(value, '[]'))) {
3096 listener.beginConstLiteral(token); 3098 listener.beginConstLiteral(token);
3097 listener.handleNoTypeArguments(token); 3099 listener.handleNoTypeArguments(token);
3098 token = parseLiteralListSuffix(token, constKeyword); 3100 token = parseLiteralListSuffix(token, constKeyword);
3099 listener.endConstLiteral(token); 3101 listener.endConstLiteral(token);
3100 return token; 3102 return token;
3101 } 3103 }
3102 if (identical(value, '{')) { 3104 if (identical(value, '{')) {
3103 listener.beginConstLiteral(token); 3105 listener.beginConstLiteral(token);
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
3206 3208
3207 Token parseLiteralNull(Token token) { 3209 Token parseLiteralNull(Token token) {
3208 listener.handleLiteralNull(token); 3210 listener.handleLiteralNull(token);
3209 return token.next; 3211 return token.next;
3210 } 3212 }
3211 3213
3212 Token parseSend(Token token, IdentifierContext context) { 3214 Token parseSend(Token token, IdentifierContext context) {
3213 Token beginToken = token; 3215 Token beginToken = token;
3214 listener.beginSend(token); 3216 listener.beginSend(token);
3215 token = parseIdentifier(token, context); 3217 token = parseIdentifier(token, context);
3216 token = _injectGenericCommentTypeList(token); 3218 token = listener.injectGenericCommentTypeList(token);
3217 if (isValidMethodTypeArguments(token)) { 3219 if (isValidMethodTypeArguments(token)) {
3218 token = parseTypeArgumentsOpt(token); 3220 token = parseTypeArgumentsOpt(token);
3219 } else { 3221 } else {
3220 listener.handleNoTypeArguments(token); 3222 listener.handleNoTypeArguments(token);
3221 } 3223 }
3222 token = parseArgumentsOpt(token); 3224 token = parseArgumentsOpt(token);
3223 listener.endSend(beginToken, token); 3225 listener.endSend(beginToken, token);
3224 return token; 3226 return token;
3225 } 3227 }
3226 3228
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
3312 3314
3313 Token parseVariablesDeclarationNoSemicolon(Token token) { 3315 Token parseVariablesDeclarationNoSemicolon(Token token) {
3314 // Only called when parsing a for loop, so this is for parsing locals. 3316 // Only called when parsing a for loop, so this is for parsing locals.
3315 return parseVariablesDeclarationMaybeSemicolon(token, false); 3317 return parseVariablesDeclarationMaybeSemicolon(token, false);
3316 } 3318 }
3317 3319
3318 Token parseVariablesDeclarationMaybeSemicolon( 3320 Token parseVariablesDeclarationMaybeSemicolon(
3319 Token token, bool endWithSemicolon) { 3321 Token token, bool endWithSemicolon) {
3320 int count = 1; 3322 int count = 1;
3321 token = parseMetadataStar(token); 3323 token = parseMetadataStar(token);
3324
3325 // If the next token has a type substitution comment /*=T*/, then
3326 // the current 'var' token should be repealed and replaced.
3327 if (identical('var', token.stringValue)) {
3328 token =
3329 listener.replaceTokenWithGenericCommentTypeAssign(token, token.next);
3330 }
3331
3322 token = parseModifiers(token); 3332 token = parseModifiers(token);
3323 token = parseTypeOpt(token); 3333 token = parseTypeOpt(token);
3324 listener.beginVariablesDeclaration(token); 3334 listener.beginVariablesDeclaration(token);
3325 token = parseOptionallyInitializedIdentifier(token); 3335 token = parseOptionallyInitializedIdentifier(token);
3326 while (optional(',', token)) { 3336 while (optional(',', token)) {
3327 token = parseOptionallyInitializedIdentifier(token.next); 3337 token = parseOptionallyInitializedIdentifier(token.next);
3328 ++count; 3338 ++count;
3329 } 3339 }
3330 if (endWithSemicolon) { 3340 if (endWithSemicolon) {
3331 Token semicolon = token; 3341 Token semicolon = token;
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after
3804 Token token, FastaCode<TokenArgument> code) { 3814 Token token, FastaCode<TokenArgument> code) {
3805 return reportUnrecoverableError( 3815 return reportUnrecoverableError(
3806 token, () => code.format(uri, token.charOffset, token)); 3816 token, () => code.format(uri, token.charOffset, token));
3807 } 3817 }
3808 3818
3809 Token reportUnrecoverableErrorCodeWithString( 3819 Token reportUnrecoverableErrorCodeWithString(
3810 Token token, FastaCode<StringArgument> code, String string) { 3820 Token token, FastaCode<StringArgument> code, String string) {
3811 return reportUnrecoverableError( 3821 return reportUnrecoverableError(
3812 token, () => code.format(uri, token.charOffset, string)); 3822 token, () => code.format(uri, token.charOffset, string));
3813 } 3823 }
3814
3815 /// Matches a generic comment type parameters or type arguments and injects
3816 /// them into the token stream before the given [token].
3817 Token _injectGenericCommentTypeList(Token token) {
3818 return _injectGenericComment(token, GENERIC_METHOD_TYPE_LIST, 2);
3819 }
3820
3821 /// Check if the given [token] has a comment token with the given [info],
3822 /// which should be either [GENERIC_METHOD_TYPE_ASSIGN] or
3823 /// [GENERIC_METHOD_TYPE_LIST]. If found, parse the comment into tokens and
3824 /// inject into the token stream before the [token].
3825 Token _injectGenericComment(Token token, PrecedenceInfo info, int prefixLen) {
3826 if (parseGenericMethodComments) {
3827 CommentToken t = token.precedingCommentTokens;
3828 for (; t != null; t = t.next) {
3829 if (t.info == info) {
3830 String code = t.lexeme.substring(prefixLen, t.lexeme.length - 2);
3831 Token tokens = _scanGenericMethodComment(code, t.offset + prefixLen);
3832 if (tokens != null) {
3833 // Remove the token from the comment stream.
3834 t.remove();
3835 // Insert the tokens into the stream.
3836 _injectTokenList(token, tokens);
3837 return tokens;
3838 }
3839 }
3840 }
3841 }
3842 return token;
3843 }
3844
3845 /// Scans the given [code], and returns the tokens, otherwise returns `null`.
3846 Token _scanGenericMethodComment(String code, int offset) {
3847 var scanner = new SubStringScanner(offset, code);
3848 Token firstToken = scanner.tokenize();
3849 if (scanner.hasErrors) {
3850 return null;
3851 }
3852 return firstToken;
3853 }
3854
3855 void _injectTokenList(Token beforeToken, Token firstToken) {
3856 // Scanner creates a cyclic EOF token.
3857 Token lastToken = firstToken;
3858 while (lastToken.next.info != EOF_INFO) {
3859 lastToken = lastToken.next;
3860 }
3861 // Inject these new tokens into the stream.
3862 Token previous = beforeToken.previous;
3863 lastToken.setNext(beforeToken);
3864 previous.setNext(firstToken);
3865 beforeToken = firstToken;
3866 }
3867 } 3824 }
3868 3825
3869 typedef FastaMessage NoArgument(Uri uri, int charOffset); 3826 typedef FastaMessage NoArgument(Uri uri, int charOffset);
3870 3827
3871 typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token); 3828 typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token);
3872 3829
3873 typedef FastaMessage StringArgument(Uri uri, int charOffset, String string); 3830 typedef FastaMessage StringArgument(Uri uri, int charOffset, String string);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698