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

Side by Side Diff: pkg/front_end/test/scanner_fasta_test.dart

Issue 2680903002: Separate fasta and analyzer scanner tests. (Closed)
Patch Set: Created 3 years, 10 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
« no previous file with comments | « no previous file | pkg/front_end/test/scanner_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
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.
4
5 import 'package:front_end/src/fasta/scanner/error_token.dart' as fasta;
6 import 'package:front_end/src/fasta/scanner/keyword.dart' as fasta;
7 import 'package:front_end/src/fasta/scanner/string_scanner.dart' as fasta;
8 import 'package:front_end/src/fasta/scanner/token.dart' as fasta;
9 import 'package:front_end/src/fasta/scanner/token_constants.dart' as fasta;
10 import 'package:front_end/src/scanner/errors.dart';
11 import 'package:front_end/src/scanner/token.dart';
12 import 'package:test/test.dart';
13 import 'package:test_reflective_loader/test_reflective_loader.dart';
14
15 import 'scanner_test.dart';
16
17 main() {
18 defineReflectiveSuite(() {
19 defineReflectiveTests(ScannerTest_Fasta);
20 });
21 }
22
23 @reflectiveTest
24 class ScannerTest_Fasta extends ScannerTestBase {
25 final _keywordMap = {
26 "assert": Keyword.ASSERT,
27 "break": Keyword.BREAK,
28 "case": Keyword.CASE,
29 "catch": Keyword.CATCH,
30 "class": Keyword.CLASS,
31 "const": Keyword.CONST,
32 "continue": Keyword.CONTINUE,
33 "default": Keyword.DEFAULT,
34 "do": Keyword.DO,
35 "else": Keyword.ELSE,
36 "enum": Keyword.ENUM,
37 "extends": Keyword.EXTENDS,
38 "false": Keyword.FALSE,
39 "final": Keyword.FINAL,
40 "finally": Keyword.FINALLY,
41 "for": Keyword.FOR,
42 "if": Keyword.IF,
43 "in": Keyword.IN,
44 "new": Keyword.NEW,
45 "null": Keyword.NULL,
46 "rethrow": Keyword.RETHROW,
47 "return": Keyword.RETURN,
48 "super": Keyword.SUPER,
49 "switch": Keyword.SWITCH,
50 "this": Keyword.THIS,
51 "throw": Keyword.THROW,
52 "true": Keyword.TRUE,
53 "try": Keyword.TRY,
54 "var": Keyword.VAR,
55 "void": Keyword.VOID,
56 "while": Keyword.WHILE,
57 "with": Keyword.WITH,
58 "is": Keyword.IS,
59 "abstract": Keyword.ABSTRACT,
60 "as": Keyword.AS,
61 "covariant": Keyword.COVARIANT,
62 "dynamic": Keyword.DYNAMIC,
63 "export": Keyword.EXPORT,
64 "external": Keyword.EXTERNAL,
65 "factory": Keyword.FACTORY,
66 "get": Keyword.GET,
67 "implements": Keyword.IMPLEMENTS,
68 "import": Keyword.IMPORT,
69 "library": Keyword.LIBRARY,
70 "operator": Keyword.OPERATOR,
71 "part": Keyword.PART,
72 "set": Keyword.SET,
73 "static": Keyword.STATIC,
74 "typedef": Keyword.TYPEDEF,
75 "deferred": Keyword.DEFERRED,
76 };
77
78 @override
79 Token scanWithListener(String source, ErrorListener listener,
80 {bool genericMethodComments: false,
81 bool lazyAssignmentOperators: false}) {
82 if (genericMethodComments) {
83 // Fasta doesn't support generic method comments.
84 // TODO(paulberry): once the analyzer toolchain no longer needs generic
85 // method comments, remove tests that exercise them.
86 fail('No generic method comment support in Fasta');
87 }
88 // Note: Fasta always supports lazy assignment operators (`&&=` and `||=`),
89 // so we can ignore the `lazyAssignmentOperators` flag.
90 // TODO(paulberry): once lazyAssignmentOperators are fully supported by
91 // Dart, remove this flag.
92 var scanner = new fasta.StringScanner(source, includeComments: true);
93 var token = scanner.tokenize();
94 var analyzerTokenHead = new Token(null, 0);
95 analyzerTokenHead.previous = analyzerTokenHead;
96 var analyzerTokenTail = analyzerTokenHead;
97 // TODO(paulberry,ahe): Fasta includes comments directly in the token
98 // stream, rather than pointing to them via a "precedingComment" pointer, as
99 // analyzer does. This seems like it will complicate parsing and other
100 // operations.
101 CommentToken currentCommentHead;
102 CommentToken currentCommentTail;
103 while (true) {
104 if (scanner.hasErrors && token is fasta.ErrorToken) {
105 var error = _translateErrorToken(token, source.length);
106 if (error != null) {
107 listener.errors.add(error);
108 }
109 } else if (token is fasta.StringToken &&
110 token.info.kind == fasta.COMMENT_TOKEN) {
111 // TODO(paulberry,ahe): It would be nice if the scanner gave us an
112 // easier way to distinguish between the two types of comment.
113 var type = token.value.startsWith('/*')
114 ? TokenType.MULTI_LINE_COMMENT
115 : TokenType.SINGLE_LINE_COMMENT;
116 var translatedToken =
117 new CommentToken(type, token.value, token.charOffset);
118 if (currentCommentHead == null) {
119 currentCommentHead = currentCommentTail = translatedToken;
120 } else {
121 currentCommentTail.setNext(translatedToken);
122 currentCommentTail = translatedToken;
123 }
124 } else {
125 var translatedToken = _translateToken(token, currentCommentHead);
126 translatedToken.setNext(translatedToken);
127 currentCommentHead = currentCommentTail = null;
128 analyzerTokenTail.setNext(translatedToken);
129 translatedToken.previous = analyzerTokenTail;
130 analyzerTokenTail = translatedToken;
131 }
132 if (token.isEof) {
133 return analyzerTokenHead.next;
134 }
135 token = token.next;
136 }
137 }
138
139 @override
140 @failingTest
141 void test_ampersand_ampersand_eq() {
142 // TODO(paulberry,ahe): Fasta doesn't support `&&=` yet
143 super.test_ampersand_ampersand_eq();
144 }
145
146 @override
147 @failingTest
148 void test_bar_bar_eq() {
149 // TODO(paulberry,ahe): Fasta doesn't support `||=` yet
150 super.test_bar_bar_eq();
151 }
152
153 @override
154 @failingTest
155 void test_comment_generic_method_type_assign() {
156 // TODO(paulberry,ahe): Fasta doesn't support generic method comment syntax.
157 super.test_comment_generic_method_type_assign();
158 }
159
160 @override
161 @failingTest
162 void test_comment_generic_method_type_list() {
163 // TODO(paulberry,ahe): Fasta doesn't support generic method comment syntax.
164 super.test_comment_generic_method_type_list();
165 }
166
167 @override
168 @failingTest
169 void test_index() {
170 // TODO(paulberry,ahe): "[]" should be parsed as a single token.
171 super.test_index();
172 }
173
174 @override
175 @failingTest
176 void test_index_eq() {
177 // TODO(paulberry,ahe): "[]=" should be parsed as a single token.
178 super.test_index_eq();
179 }
180
181 @override
182 @failingTest
183 void test_scriptTag_withArgs() {
184 // TODO(paulberry,ahe): script tags are needed by analyzer.
185 super.test_scriptTag_withArgs();
186 }
187
188 @override
189 @failingTest
190 void test_scriptTag_withoutSpace() {
191 // TODO(paulberry,ahe): script tags are needed by analyzer.
192 super.test_scriptTag_withoutSpace();
193 }
194
195 @override
196 @failingTest
197 void test_scriptTag_withSpace() {
198 // TODO(paulberry,ahe): script tags are needed by analyzer.
199 super.test_scriptTag_withSpace();
200 }
201
202 @override
203 @failingTest
204 void test_string_multi_unterminated() {
205 // TODO(paulberry,ahe): bad error recovery.
206 super.test_string_multi_unterminated();
207 }
208
209 @override
210 @failingTest
211 void test_string_multi_unterminated_interpolation_block() {
212 // TODO(paulberry,ahe): bad error recovery.
213 super.test_string_multi_unterminated_interpolation_block();
214 }
215
216 @override
217 @failingTest
218 void test_string_multi_unterminated_interpolation_identifier() {
219 // TODO(paulberry,ahe): bad error recovery.
220 super.test_string_multi_unterminated_interpolation_identifier();
221 }
222
223 @override
224 @failingTest
225 void test_string_raw_multi_unterminated() {
226 // TODO(paulberry,ahe): bad error recovery.
227 super.test_string_raw_multi_unterminated();
228 }
229
230 @override
231 @failingTest
232 void test_string_raw_simple_unterminated_eof() {
233 // TODO(paulberry,ahe): bad error recovery.
234 super.test_string_raw_simple_unterminated_eof();
235 }
236
237 @override
238 @failingTest
239 void test_string_raw_simple_unterminated_eol() {
240 // TODO(paulberry,ahe): bad error recovery.
241 super.test_string_raw_simple_unterminated_eol();
242 }
243
244 @override
245 @failingTest
246 void test_string_simple_unterminated_eof() {
247 // TODO(paulberry,ahe): bad error recovery.
248 super.test_string_simple_unterminated_eof();
249 }
250
251 @override
252 @failingTest
253 void test_string_simple_unterminated_eol() {
254 // TODO(paulberry,ahe): bad error recovery.
255 super.test_string_simple_unterminated_eol();
256 }
257
258 @override
259 @failingTest
260 void test_string_simple_unterminated_interpolation_block() {
261 // TODO(paulberry,ahe): bad error recovery.
262 super.test_string_simple_unterminated_interpolation_block();
263 }
264
265 @override
266 @failingTest
267 void test_string_simple_unterminated_interpolation_identifier() {
268 // TODO(paulberry,ahe): bad error recovery.
269 super.test_string_simple_unterminated_interpolation_identifier();
270 }
271
272 TestError _translateErrorToken(fasta.ErrorToken token, int inputLength) {
273 int charOffset = token.charOffset;
274 // TODO(paulberry,ahe): why is endOffset sometimes null?
275 int endOffset = token.endOffset ?? charOffset;
276 TestError _makeError(ScannerErrorCode errorCode, List<Object> arguments) {
277 int errorLength = endOffset - charOffset;
278 if (charOffset == inputLength) {
279 // Analyzer never generates an error message past the end of the input,
280 // since such an error would not be visible in an editor.
281 // TODO(paulberry,ahe): would it make sense to replicate this behavior
282 // in fasta, or move it elsewhere in analyzer?
283 charOffset--;
284 }
285 if (errorLength == 0) {
286 // Analyzer never generates an error message of length zero,
287 // since such an error would not be visible in an editor.
288 // TODO(paulberry,ahe): would it make sense to replicate this behavior
289 // in fasta, or move it elsewhere in analyzer?
290 errorLength = 1;
291 }
292 return new TestError(charOffset, errorLength, errorCode, arguments);
293 }
294
295 var errorCode = token.errorCode;
296 switch (errorCode) {
297 case fasta.ErrorKind.UnterminatedString:
298 // TODO(paulberry,ahe): Fasta reports the error location as the entire
299 // string; analyzer expects the end of the string.
300 charOffset = endOffset;
301 return _makeError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, null);
302 case fasta.ErrorKind.UnmatchedToken:
303 return null;
304 case fasta.ErrorKind.UnterminatedComment:
305 // TODO(paulberry,ahe): Fasta reports the error location as the entire
306 // comment; analyzer expects the end of the comment.
307 charOffset = endOffset;
308 return _makeError(
309 ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT, null);
310 case fasta.ErrorKind.MissingExponent:
311 // TODO(paulberry,ahe): Fasta reports the error location as the entire
312 // number; analyzer expects the end of the number.
313 charOffset = endOffset;
314 return _makeError(ScannerErrorCode.MISSING_DIGIT, null);
315 case fasta.ErrorKind.ExpectedHexDigit:
316 // TODO(paulberry,ahe): Fasta reports the error location as the entire
317 // number; analyzer expects the end of the number.
318 charOffset = endOffset;
319 return _makeError(ScannerErrorCode.MISSING_HEX_DIGIT, null);
320 case fasta.ErrorKind.NonAsciiIdentifier:
321 case fasta.ErrorKind.NonAsciiWhitespace:
322 return _makeError(
323 ScannerErrorCode.ILLEGAL_CHARACTER, [token.character]);
324 case fasta.ErrorKind.UnexpectedDollarInString:
325 return null;
326 default:
327 throw new UnimplementedError('$errorCode');
328 }
329 }
330
331 Keyword _translateKeyword(String syntax) =>
332 _keywordMap[syntax] ?? (throw new UnimplementedError('$syntax'));
333
334 Token _translateToken(fasta.Token token, CommentToken comment) {
335 var type = _translateTokenInfoKind(token.info.kind);
336 int offset = token.charOffset;
337 Token makeStringToken(String value) {
338 if (comment == null) {
339 return new StringToken(type, value, offset);
340 } else {
341 return new StringTokenWithComment(type, value, offset, comment);
342 }
343 }
344
345 Token makeKeywordToken(Keyword keyword) {
346 if (comment == null) {
347 return new KeywordToken(keyword, offset);
348 } else {
349 return new KeywordTokenWithComment(keyword, offset, comment);
350 }
351 }
352
353 Token makeBeginToken() {
354 if (comment == null) {
355 return new BeginToken(type, offset);
356 } else {
357 return new BeginTokenWithComment(type, offset, comment);
358 }
359 }
360
361 if (token is fasta.StringToken) {
362 return makeStringToken(token.value);
363 } else if (token is fasta.KeywordToken) {
364 return makeKeywordToken(_translateKeyword(token.keyword.syntax));
365 } else if (token is fasta.SymbolToken) {
366 if (token is fasta.BeginGroupToken) {
367 if (type == TokenType.LT) {
368 return makeStringToken(token.value);
369 } else {
370 return makeBeginToken();
371 }
372 } else {
373 return makeStringToken(token.value);
374 }
375 }
376 throw new UnimplementedError('${token.runtimeType}');
377 }
378
379 TokenType _translateTokenInfoKind(int kind) {
380 switch (kind) {
381 case fasta.EOF_TOKEN:
382 return TokenType.EOF;
383 case fasta.KEYWORD_TOKEN:
384 return TokenType.KEYWORD;
385 case fasta.IDENTIFIER_TOKEN:
386 return TokenType.IDENTIFIER;
387 case fasta.BAD_INPUT_TOKEN:
388 return TokenType.STRING;
389 case fasta.DOUBLE_TOKEN:
390 return TokenType.DOUBLE;
391 case fasta.INT_TOKEN:
392 return TokenType.INT;
393 case fasta.HEXADECIMAL_TOKEN:
394 return TokenType.HEXADECIMAL;
395 case fasta.STRING_TOKEN:
396 return TokenType.STRING;
397 case fasta.AMPERSAND_TOKEN:
398 return TokenType.AMPERSAND;
399 case fasta.BACKPING_TOKEN:
400 return TokenType.BACKPING;
401 case fasta.BACKSLASH_TOKEN:
402 return TokenType.BACKSLASH;
403 case fasta.BANG_TOKEN:
404 return TokenType.BANG;
405 case fasta.BAR_TOKEN:
406 return TokenType.BAR;
407 case fasta.COLON_TOKEN:
408 return TokenType.COLON;
409 case fasta.COMMA_TOKEN:
410 return TokenType.COMMA;
411 case fasta.EQ_TOKEN:
412 return TokenType.EQ;
413 case fasta.GT_TOKEN:
414 return TokenType.GT;
415 case fasta.HASH_TOKEN:
416 return TokenType.HASH;
417 case fasta.OPEN_CURLY_BRACKET_TOKEN:
418 return TokenType.OPEN_CURLY_BRACKET;
419 case fasta.OPEN_SQUARE_BRACKET_TOKEN:
420 return TokenType.OPEN_SQUARE_BRACKET;
421 case fasta.OPEN_PAREN_TOKEN:
422 return TokenType.OPEN_PAREN;
423 case fasta.LT_TOKEN:
424 return TokenType.LT;
425 case fasta.MINUS_TOKEN:
426 return TokenType.MINUS;
427 case fasta.PERIOD_TOKEN:
428 return TokenType.PERIOD;
429 case fasta.PLUS_TOKEN:
430 return TokenType.PLUS;
431 case fasta.QUESTION_TOKEN:
432 return TokenType.QUESTION;
433 case fasta.AT_TOKEN:
434 return TokenType.AT;
435 case fasta.CLOSE_CURLY_BRACKET_TOKEN:
436 return TokenType.CLOSE_CURLY_BRACKET;
437 case fasta.CLOSE_SQUARE_BRACKET_TOKEN:
438 return TokenType.CLOSE_SQUARE_BRACKET;
439 case fasta.CLOSE_PAREN_TOKEN:
440 return TokenType.CLOSE_PAREN;
441 case fasta.SEMICOLON_TOKEN:
442 return TokenType.SEMICOLON;
443 case fasta.SLASH_TOKEN:
444 return TokenType.SLASH;
445 case fasta.TILDE_TOKEN:
446 return TokenType.TILDE;
447 case fasta.STAR_TOKEN:
448 return TokenType.STAR;
449 case fasta.PERCENT_TOKEN:
450 return TokenType.PERCENT;
451 case fasta.CARET_TOKEN:
452 return TokenType.CARET;
453 case fasta.STRING_INTERPOLATION_TOKEN:
454 return TokenType.STRING_INTERPOLATION_EXPRESSION;
455 case fasta.LT_EQ_TOKEN:
456 return TokenType.LT_EQ;
457 case fasta.FUNCTION_TOKEN:
458 return TokenType.FUNCTION;
459 case fasta.SLASH_EQ_TOKEN:
460 return TokenType.SLASH_EQ;
461 case fasta.PERIOD_PERIOD_PERIOD_TOKEN:
462 return TokenType.PERIOD_PERIOD_PERIOD;
463 case fasta.PERIOD_PERIOD_TOKEN:
464 return TokenType.PERIOD_PERIOD;
465 case fasta.EQ_EQ_EQ_TOKEN:
466 // TODO(paulberry,ahe): what is this?
467 throw new UnimplementedError();
468 case fasta.EQ_EQ_TOKEN:
469 return TokenType.EQ_EQ;
470 case fasta.LT_LT_EQ_TOKEN:
471 return TokenType.LT_LT_EQ;
472 case fasta.LT_LT_TOKEN:
473 return TokenType.LT_LT;
474 case fasta.GT_EQ_TOKEN:
475 return TokenType.GT_EQ;
476 case fasta.GT_GT_EQ_TOKEN:
477 return TokenType.GT_GT_EQ;
478 case fasta.INDEX_EQ_TOKEN:
479 return TokenType.INDEX_EQ;
480 case fasta.INDEX_TOKEN:
481 return TokenType.INDEX;
482 case fasta.BANG_EQ_EQ_TOKEN:
483 // TODO(paulberry,ahe): what is this?
484 throw new UnimplementedError();
485 case fasta.BANG_EQ_TOKEN:
486 return TokenType.BANG_EQ;
487 case fasta.AMPERSAND_AMPERSAND_TOKEN:
488 return TokenType.AMPERSAND_AMPERSAND;
489 case fasta.AMPERSAND_EQ_TOKEN:
490 return TokenType.AMPERSAND_EQ;
491 case fasta.BAR_BAR_TOKEN:
492 return TokenType.BAR_BAR;
493 case fasta.BAR_EQ_TOKEN:
494 return TokenType.BAR_EQ;
495 case fasta.STAR_EQ_TOKEN:
496 return TokenType.STAR_EQ;
497 case fasta.PLUS_PLUS_TOKEN:
498 return TokenType.PLUS_PLUS;
499 case fasta.PLUS_EQ_TOKEN:
500 return TokenType.PLUS_EQ;
501 case fasta.MINUS_MINUS_TOKEN:
502 return TokenType.MINUS_MINUS;
503 case fasta.MINUS_EQ_TOKEN:
504 return TokenType.MINUS_EQ;
505 case fasta.TILDE_SLASH_EQ_TOKEN:
506 return TokenType.TILDE_SLASH_EQ;
507 case fasta.TILDE_SLASH_TOKEN:
508 return TokenType.TILDE_SLASH;
509 case fasta.PERCENT_EQ_TOKEN:
510 return TokenType.PERCENT_EQ;
511 case fasta.GT_GT_TOKEN:
512 return TokenType.GT_GT;
513 case fasta.CARET_EQ_TOKEN:
514 return TokenType.CARET_EQ;
515 case fasta.STRING_INTERPOLATION_IDENTIFIER_TOKEN:
516 return TokenType.STRING_INTERPOLATION_IDENTIFIER;
517 case fasta.QUESTION_PERIOD_TOKEN:
518 return TokenType.QUESTION_PERIOD;
519 case fasta.QUESTION_QUESTION_TOKEN:
520 return TokenType.QUESTION_QUESTION;
521 case fasta.QUESTION_QUESTION_EQ_TOKEN:
522 return TokenType.QUESTION_QUESTION_EQ;
523 default:
524 throw new UnimplementedError('$kind');
525 }
526 }
527 }
OLDNEW
« no previous file with comments | « no previous file | pkg/front_end/test/scanner_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698