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

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

Issue 2676083002: Connect fasta's scanner to the analyzer-derived scanner tests in front_end. (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 | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, 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 import 'package:front_end/src/base/errors.dart'; 5 import 'package:front_end/src/base/errors.dart';
6 import 'package:front_end/src/base/jenkins_smi_hash.dart'; 6 import 'package:front_end/src/base/jenkins_smi_hash.dart';
7 import 'package:front_end/src/fasta/scanner/error_token.dart' as fasta;
8 import 'package:front_end/src/fasta/scanner/keyword.dart' as fasta;
9 import 'package:front_end/src/fasta/scanner/string_scanner.dart' as fasta;
10 import 'package:front_end/src/fasta/scanner/token.dart' as fasta;
11 import 'package:front_end/src/fasta/scanner/token_constants.dart' as fasta;
7 import 'package:front_end/src/scanner/errors.dart'; 12 import 'package:front_end/src/scanner/errors.dart';
8 import 'package:front_end/src/scanner/reader.dart'; 13 import 'package:front_end/src/scanner/reader.dart';
9 import 'package:front_end/src/scanner/scanner.dart'; 14 import 'package:front_end/src/scanner/scanner.dart';
10 import 'package:front_end/src/scanner/token.dart'; 15 import 'package:front_end/src/scanner/token.dart';
11 import 'package:test/test.dart'; 16 import 'package:test/test.dart';
12 import 'package:test_reflective_loader/test_reflective_loader.dart'; 17 import 'package:test_reflective_loader/test_reflective_loader.dart';
13 18
14 main() { 19 main() {
15 defineReflectiveSuite(() { 20 defineReflectiveSuite(() {
16 defineReflectiveTests(CharSequenceReaderTest); 21 defineReflectiveTests(CharSequenceReaderTest);
17 defineReflectiveTests(KeywordStateTest); 22 defineReflectiveTests(KeywordStateTest);
18 defineReflectiveTests(ScannerTest); 23 defineReflectiveTests(ScannerTest);
Paul Berry 2017/02/03 23:10:36 Note that this test file now tests both the analyz
24 defineReflectiveTests(ScannerTest_Fasta);
19 defineReflectiveTests(TokenTypeTest); 25 defineReflectiveTests(TokenTypeTest);
20 }); 26 });
21 } 27 }
22 28
23 @reflectiveTest 29 @reflectiveTest
24 class CharSequenceReaderTest { 30 class CharSequenceReaderTest {
25 void test_advance() { 31 void test_advance() {
26 CharSequenceReader reader = new CharSequenceReader("x"); 32 CharSequenceReader reader = new CharSequenceReader("x");
27 expect(reader.advance(), 0x78); 33 expect(reader.advance(), 0x78);
28 expect(reader.advance(), -1); 34 expect(reader.advance(), -1);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 expect(state, isNull); 112 expect(state, isNull);
107 } else { 113 } else {
108 // keyword.substring(0, keyword.length() - 1) 114 // keyword.substring(0, keyword.length() - 1)
109 expect(state, isNotNull); 115 expect(state, isNotNull);
110 } 116 }
111 } 117 }
112 } 118 }
113 } 119 }
114 120
115 @reflectiveTest 121 @reflectiveTest
116 class ScannerTest { 122 class ScannerTest extends ScannerTestBase {
123 @override
124 Token _scanWithListener(String source, _ErrorListener listener,
125 {bool genericMethodComments: false,
126 bool lazyAssignmentOperators: false}) {
127 Scanner scanner =
128 new _TestScanner(new CharSequenceReader(source), listener);
129 scanner.scanGenericMethodComments = genericMethodComments;
130 scanner.scanLazyAssignmentOperators = lazyAssignmentOperators;
131 return scanner.tokenize();
132 }
133 }
134
135 @reflectiveTest
136 class ScannerTest_Fasta extends ScannerTestBase {
137 final _keywordMap = {
138 "assert": Keyword.ASSERT,
139 "break": Keyword.BREAK,
140 "case": Keyword.CASE,
141 "catch": Keyword.CATCH,
142 "class": Keyword.CLASS,
143 "const": Keyword.CONST,
144 "continue": Keyword.CONTINUE,
145 "default": Keyword.DEFAULT,
146 "do": Keyword.DO,
147 "else": Keyword.ELSE,
148 "enum": Keyword.ENUM,
149 "extends": Keyword.EXTENDS,
150 "false": Keyword.FALSE,
151 "final": Keyword.FINAL,
152 "finally": Keyword.FINALLY,
153 "for": Keyword.FOR,
154 "if": Keyword.IF,
155 "in": Keyword.IN,
156 "new": Keyword.NEW,
157 "null": Keyword.NULL,
158 "rethrow": Keyword.RETHROW,
159 "return": Keyword.RETURN,
160 "super": Keyword.SUPER,
161 "switch": Keyword.SWITCH,
162 "this": Keyword.THIS,
163 "throw": Keyword.THROW,
164 "true": Keyword.TRUE,
165 "try": Keyword.TRY,
166 "var": Keyword.VAR,
167 "void": Keyword.VOID,
168 "while": Keyword.WHILE,
169 "with": Keyword.WITH,
170 "is": Keyword.IS,
171 "abstract": Keyword.ABSTRACT,
172 "as": Keyword.AS,
173 "covariant": Keyword.COVARIANT,
174 "dynamic": Keyword.DYNAMIC,
175 "export": Keyword.EXPORT,
176 "external": Keyword.EXTERNAL,
177 "factory": Keyword.FACTORY,
178 "get": Keyword.GET,
179 "implements": Keyword.IMPLEMENTS,
180 "import": Keyword.IMPORT,
181 "library": Keyword.LIBRARY,
182 "operator": Keyword.OPERATOR,
183 "part": Keyword.PART,
184 "set": Keyword.SET,
185 "static": Keyword.STATIC,
186 "typedef": Keyword.TYPEDEF,
187 "deferred": Keyword.DEFERRED,
188 };
189
190 @override
191 @failingTest
Paul Berry 2017/02/03 23:10:36 Note: these overrides indicate to the test_reflect
192 void test_ampersand_ampersand_eq() {
193 // TODO(paulberry,ahe): Fasta doesn't support `&&=` yet
194 super.test_ampersand_ampersand_eq();
195 }
196
197 @override
198 @failingTest
199 void test_bar_bar_eq() {
200 // TODO(paulberry,ahe): Fasta doesn't support `||=` yet
201 super.test_bar_bar_eq();
202 }
203
204 @override
205 @failingTest
206 void test_comment_generic_method_type_assign() {
207 // TODO(paulberry,ahe): Fasta doesn't support generic method comment syntax.
ahe 2017/02/06 11:01:20 Do you think that would be necessary to support in
Paul Berry 2017/02/06 13:46:54 It's not clear at this point. I asked Dan Grove a
208 super.test_comment_generic_method_type_assign();
209 }
210
211 @override
212 @failingTest
213 void test_comment_generic_method_type_list() {
214 // TODO(paulberry,ahe): Fasta doesn't support generic method comment syntax.
215 super.test_comment_generic_method_type_list();
216 }
217
218 @override
219 @failingTest
220 void test_comment_multi_unterminated() {
221 // TODO(paulberry,ahe): see UnimplementedError("distinguish unterminated err ors")
ahe 2017/02/06 11:01:20 Long line here and a few below.
Paul Berry 2017/02/06 13:46:54 Done.
222 super.test_comment_multi_unterminated();
223 }
224
225 @override
226 @failingTest
227 void test_comment_single() {
228 // TODO(paulberry,ahe): See TODO comment below in _translateTokenInfoKind().
229 super.test_comment_single();
230 }
231
232 @override
233 @failingTest
234 void test_double_missingDigitInExponent() {
235 // TODO(paulberry,ahe): see UnimplementedError("distinguish unterminated err ors")
236 super.test_double_missingDigitInExponent();
237 }
238
239 @override
240 @failingTest
241 void test_hexidecimal_missingDigit() {
242 // TODO(paulberry,ahe): see UnimplementedError("distinguish unterminated err ors")
243 super.test_hexidecimal_missingDigit();
244 }
245
246 @override
247 @failingTest
248 void test_index() {
249 // TODO(paulberry,ahe): "[]" should be parsed as a single token.
ahe 2017/02/04 09:48:19 Note: [] and []= are tokenized as a single token o
Paul Berry 2017/02/04 14:57:55 Interesting. The behavior of the analyzer scanner
ahe 2017/02/06 11:01:20 I agree. A corner case with the dart2js/fasta appr
Paul Berry 2017/02/06 13:46:54 SGTM.
Siggi Cherem (dart-lang) 2017/02/06 23:51:29 A small question: could we annotate somehow these
Paul Berry 2017/02/07 13:56:11 I've filed an issue: https://github.com/dart-lang/
250 super.test_index();
251 }
252
253 @override
254 @failingTest
255 void test_index_eq() {
256 // TODO(paulberry,ahe): "[]=" should be parsed as a single token.
257 super.test_index_eq();
258 }
259
260 @override
261 @failingTest
262 void test_scriptTag_withArgs() {
263 // TODO(paulberry,ahe): script tags are needed by analyzer.
264 super.test_scriptTag_withArgs();
265 }
266
267 @override
268 @failingTest
269 void test_scriptTag_withoutSpace() {
270 // TODO(paulberry,ahe): script tags are needed by analyzer.
271 super.test_scriptTag_withoutSpace();
272 }
273
274 @override
275 @failingTest
276 void test_scriptTag_withSpace() {
277 // TODO(paulberry,ahe): script tags are needed by analyzer.
278 super.test_scriptTag_withSpace();
279 }
280
281 @override
282 @failingTest
283 void test_string_multi_unterminated() {
284 // TODO(paulberry,ahe): bad error recovery.
285 super.test_string_multi_unterminated();
286 }
287
288 @override
289 @failingTest
290 void test_string_multi_unterminated_interpolation_block() {
291 // TODO(paulberry,ahe): bad error recovery.
292 super.test_string_multi_unterminated_interpolation_block();
293 }
294
295 @override
296 @failingTest
297 void test_string_multi_unterminated_interpolation_identifier() {
298 // TODO(paulberry,ahe): bad error recovery.
299 super.test_string_multi_unterminated_interpolation_identifier();
300 }
301
302 @override
303 @failingTest
304 void test_string_raw_multi_unterminated() {
305 // TODO(paulberry,ahe): bad error recovery.
306 super.test_string_raw_multi_unterminated();
307 }
308
309 @override
310 @failingTest
311 void test_string_raw_simple_unterminated_eof() {
312 // TODO(paulberry,ahe): bad error recovery.
313 super.test_string_raw_simple_unterminated_eof();
314 }
315
316 @override
317 @failingTest
318 void test_string_raw_simple_unterminated_eol() {
319 // TODO(paulberry,ahe): bad error recovery.
320 super.test_string_raw_simple_unterminated_eol();
321 }
322
323 @override
324 @failingTest
325 void test_string_simple_interpolation_missingIdentifier() {
326 // TODO(paulberry,ahe): bad error recovery.
327 super.test_string_simple_interpolation_missingIdentifier();
328 }
329
330 @override
331 @failingTest
332 void test_string_simple_interpolation_nonIdentifier() {
333 // TODO(paulberry,ahe): bad error recovery.
334 super.test_string_simple_interpolation_nonIdentifier();
335 }
336
337 @override
338 @failingTest
339 void test_string_simple_unterminated_eof() {
340 // TODO(paulberry,ahe): bad error recovery.
341 super.test_string_simple_unterminated_eof();
342 }
343
344 @override
345 @failingTest
346 void test_string_simple_unterminated_eol() {
347 // TODO(paulberry,ahe): bad error recovery.
348 super.test_string_simple_unterminated_eol();
349 }
350
351 @override
352 @failingTest
353 void test_string_simple_unterminated_interpolation_block() {
354 // TODO(paulberry,ahe): bad error recovery.
355 super.test_string_simple_unterminated_interpolation_block();
356 }
357
358 @override
359 @failingTest
360 void test_string_simple_unterminated_interpolation_identifier() {
361 // TODO(paulberry,ahe): bad error recovery.
362 super.test_string_simple_unterminated_interpolation_identifier();
363 }
364
365 @override
366 Token _scanWithListener(String source, _ErrorListener listener,
367 {bool genericMethodComments: false,
368 bool lazyAssignmentOperators: false}) {
369 if (genericMethodComments) {
370 // Fasta doesn't support generic method comments.
371 // TODO(paulberry): once the analyzer toolchain no longer needs generic
372 // method comments, remove tests that exercise them.
373 fail('No generic method comment support in Fasta');
374 }
375 // Note: Fasta always supports lazy assignment operators (`&&=` and `||=`),
376 // so we can ignore the `lazyAssignmentOperators` flag.
377 // TODO(paulberry): once lazyAssignmentOperators are fully supported by
378 // Dart, remove this flag.
379 var scanner = new fasta.StringScanner(source, includeComments: true);
380 var token = scanner.tokenize();
381 var analyzerTokenHead = new Token(null, 0);
382 analyzerTokenHead.previous = analyzerTokenHead;
383 var analyzerTokenTail = analyzerTokenHead;
384 // TODO(paulberry,ahe): Fasta includes comments directly in the token
385 // stream, rather than pointing to them via a "precedingComment" pointer, as
386 // analyzer does. This seems like it will complicate parsing and other
387 // operations.
388 CommentToken currentCommentHead;
389 CommentToken currentCommentTail;
390 while (true) {
391 if (token is fasta.ErrorToken) {
392 var error = _translateErrorToken(token, source.length);
393 if (error != null) {
394 listener.errors.add(error);
395 }
396 } else if (token is fasta.StringToken &&
397 token.info.kind == fasta.COMMENT_TOKEN) {
398 var translatedToken = _translateToken(token, null) as CommentToken;
399 if (currentCommentHead == null) {
400 currentCommentHead = currentCommentTail = translatedToken;
401 } else {
402 currentCommentTail.setNext(translatedToken);
403 currentCommentTail = translatedToken;
404 }
405 } else {
406 var translatedToken = _translateToken(token, currentCommentHead);
407 translatedToken.setNext(translatedToken);
408 currentCommentHead = currentCommentTail = null;
409 analyzerTokenTail.setNext(translatedToken);
410 translatedToken.previous = analyzerTokenTail;
411 analyzerTokenTail = translatedToken;
412 }
413 if (token.isEof) {
414 return analyzerTokenHead.next;
415 }
416 token = token.next;
417 }
418 }
419
420 _TestError _translateErrorToken(fasta.ErrorToken token, int inputLength) {
421 int charOffset = token.charOffset;
422 // TODO(paulberry,ahe): why is endOffset sometimes null?
423 int endOffset = token.endOffset ?? charOffset;
424 _TestError _makeError(ScannerErrorCode errorCode, List<Object> arguments) {
425 int errorLength = endOffset - charOffset;
426 if (charOffset == inputLength) {
427 // Analyzer never generates an error message past the end of the input,
428 // since such an error would not be visible in an editor.
429 // TODO(paulberry,ahe): would it make sense to replicate this behavior
430 // in fasta, or move it elsewhere in analyzer?
431 charOffset--;
432 }
433 if (errorLength == 0) {
434 // Analyzer never generates an error message of length zero,
435 // since such an error would not be visible in an editor.
436 // TODO(paulberry,ahe): would it make sense to replicate this behavior
437 // in fasta, or move it elsewhere in analyzer?
438 errorLength = 1;
439 }
440 return new _TestError(charOffset, errorLength, errorCode, arguments);
441 }
442
443 if (token is fasta.UnterminatedToken) {
444 // TODO(paulberry,ahe): How to tell what kind of error to
445 // report? It could be ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
446 // ScannerErrorCode.MISSING_HEX_DIGIT, or
447 // ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT
ahe 2017/02/04 09:48:19 Absolutely. Just this week, I was thinking about c
Paul Berry 2017/02/04 14:57:55 Aha, thank you. I failed to notice the presence o
ahe 2017/02/06 11:01:20 We should be careful about polymorphism, but in th
Paul Berry 2017/02/06 13:46:54 Aha, nice. When I do my rework of this code (whic
448 return _makeError(
449 throw new UnimplementedError("distinguish unterminated errors"),
450 null);
451 } else if (token is fasta.UnmatchedToken) {
452 return null;
453 } else if (token is fasta.NonAsciiIdentifierToken) {
454 return _makeError(ScannerErrorCode.ILLEGAL_CHARACTER, [token.character]);
455 } else if (token is fasta.NonAsciiWhitespaceToken) {
456 return _makeError(ScannerErrorCode.ILLEGAL_CHARACTER, [token.character]);
457 }
458 throw new UnimplementedError('${token.runtimeType}');
459 }
460
461 Keyword _translateKeyword(String syntax) =>
462 _keywordMap[syntax] ?? (throw new UnimplementedError('$syntax'));
463
464 Token _translateToken(fasta.Token token, CommentToken comment) {
465 var type = _translateTokenInfoKind(token.info.kind);
466 int offset = token.charOffset;
467 Token makeStringToken(String value) {
468 if (comment == null) {
469 return new StringToken(type, value, offset);
470 } else {
471 return new StringTokenWithComment(type, value, offset, comment);
472 }
473 }
474
475 Token makeKeywordToken(Keyword keyword) {
476 if (comment == null) {
477 return new KeywordToken(keyword, offset);
478 } else {
479 return new KeywordTokenWithComment(keyword, offset, comment);
480 }
481 }
482
483 Token makeBeginToken() {
484 if (comment == null) {
485 return new BeginToken(type, offset);
486 } else {
487 return new BeginTokenWithComment(type, offset, comment);
488 }
489 }
490
491 Token makeCommentToken() {
492 return new CommentToken(type, token.value, offset);
493 }
494
495 if (token is fasta.StringToken) {
496 if (token.info.kind == fasta.COMMENT_TOKEN) {
497 return makeCommentToken();
498 } else {
499 return makeStringToken(token.value);
500 }
501 } else if (token is fasta.KeywordToken) {
502 return makeKeywordToken(_translateKeyword(token.keyword.syntax));
503 } else if (token is fasta.SymbolToken) {
504 if (token is fasta.BeginGroupToken) {
505 if (type == TokenType.LT) {
506 return makeStringToken(token.value);
507 } else {
508 return makeBeginToken();
509 }
510 } else {
511 return makeStringToken(token.value);
512 }
513 }
514 throw new UnimplementedError('${token.runtimeType}');
515 }
516
517 TokenType _translateTokenInfoKind(int kind) {
518 switch (kind) {
519 case fasta.EOF_TOKEN:
520 return TokenType.EOF;
521 case fasta.KEYWORD_TOKEN:
522 return TokenType.KEYWORD;
523 case fasta.IDENTIFIER_TOKEN:
524 return TokenType.IDENTIFIER;
525 case fasta.BAD_INPUT_TOKEN:
526 return TokenType.STRING;
527 case fasta.DOUBLE_TOKEN:
528 return TokenType.DOUBLE;
529 case fasta.INT_TOKEN:
530 return TokenType.INT;
531 case fasta.HEXADECIMAL_TOKEN:
532 return TokenType.HEXADECIMAL;
533 case fasta.STRING_TOKEN:
534 return TokenType.STRING;
535 case fasta.AMPERSAND_TOKEN:
536 return TokenType.AMPERSAND;
537 case fasta.BACKPING_TOKEN:
538 return TokenType.BACKPING;
539 case fasta.BACKSLASH_TOKEN:
540 return TokenType.BACKSLASH;
541 case fasta.BANG_TOKEN:
542 return TokenType.BANG;
543 case fasta.BAR_TOKEN:
544 return TokenType.BAR;
545 case fasta.COLON_TOKEN:
546 return TokenType.COLON;
547 case fasta.COMMA_TOKEN:
548 return TokenType.COMMA;
549 case fasta.EQ_TOKEN:
550 return TokenType.EQ;
551 case fasta.GT_TOKEN:
552 return TokenType.GT;
553 case fasta.HASH_TOKEN:
554 return TokenType.HASH;
555 case fasta.OPEN_CURLY_BRACKET_TOKEN:
556 return TokenType.OPEN_CURLY_BRACKET;
557 case fasta.OPEN_SQUARE_BRACKET_TOKEN:
558 return TokenType.OPEN_SQUARE_BRACKET;
559 case fasta.OPEN_PAREN_TOKEN:
560 return TokenType.OPEN_PAREN;
561 case fasta.LT_TOKEN:
562 return TokenType.LT;
563 case fasta.MINUS_TOKEN:
564 return TokenType.MINUS;
565 case fasta.PERIOD_TOKEN:
566 return TokenType.PERIOD;
567 case fasta.PLUS_TOKEN:
568 return TokenType.PLUS;
569 case fasta.QUESTION_TOKEN:
570 return TokenType.QUESTION;
571 case fasta.AT_TOKEN:
572 return TokenType.AT;
573 case fasta.CLOSE_CURLY_BRACKET_TOKEN:
574 return TokenType.CLOSE_CURLY_BRACKET;
575 case fasta.CLOSE_SQUARE_BRACKET_TOKEN:
576 return TokenType.CLOSE_SQUARE_BRACKET;
577 case fasta.CLOSE_PAREN_TOKEN:
578 return TokenType.CLOSE_PAREN;
579 case fasta.SEMICOLON_TOKEN:
580 return TokenType.SEMICOLON;
581 case fasta.SLASH_TOKEN:
582 return TokenType.SLASH;
583 case fasta.TILDE_TOKEN:
584 return TokenType.TILDE;
585 case fasta.STAR_TOKEN:
586 return TokenType.STAR;
587 case fasta.PERCENT_TOKEN:
588 return TokenType.PERCENT;
589 case fasta.CARET_TOKEN:
590 return TokenType.CARET;
591 case fasta.STRING_INTERPOLATION_TOKEN:
592 return TokenType.STRING_INTERPOLATION_EXPRESSION;
593 case fasta.LT_EQ_TOKEN:
594 return TokenType.LT_EQ;
595 case fasta.FUNCTION_TOKEN:
596 return TokenType.FUNCTION;
597 case fasta.SLASH_EQ_TOKEN:
598 return TokenType.SLASH_EQ;
599 case fasta.PERIOD_PERIOD_PERIOD_TOKEN:
600 return TokenType.PERIOD_PERIOD_PERIOD;
601 case fasta.PERIOD_PERIOD_TOKEN:
602 return TokenType.PERIOD_PERIOD;
603 case fasta.EQ_EQ_EQ_TOKEN:
604 // TODO(paulberry,ahe): what is this?
605 throw new UnimplementedError();
606 case fasta.EQ_EQ_TOKEN:
607 return TokenType.EQ_EQ;
608 case fasta.LT_LT_EQ_TOKEN:
609 return TokenType.LT_LT_EQ;
610 case fasta.LT_LT_TOKEN:
611 return TokenType.LT_LT;
612 case fasta.GT_EQ_TOKEN:
613 return TokenType.GT_EQ;
614 case fasta.GT_GT_EQ_TOKEN:
615 return TokenType.GT_GT_EQ;
616 case fasta.INDEX_EQ_TOKEN:
617 return TokenType.INDEX_EQ;
618 case fasta.INDEX_TOKEN:
619 return TokenType.INDEX;
620 case fasta.BANG_EQ_EQ_TOKEN:
621 // TODO(paulberry,ahe): what is this?
622 throw new UnimplementedError();
623 case fasta.BANG_EQ_TOKEN:
624 return TokenType.BANG_EQ;
625 case fasta.AMPERSAND_AMPERSAND_TOKEN:
626 return TokenType.AMPERSAND_AMPERSAND;
627 case fasta.AMPERSAND_EQ_TOKEN:
628 return TokenType.AMPERSAND_EQ;
629 case fasta.BAR_BAR_TOKEN:
630 return TokenType.BAR_BAR;
631 case fasta.BAR_EQ_TOKEN:
632 return TokenType.BAR_EQ;
633 case fasta.STAR_EQ_TOKEN:
634 return TokenType.STAR_EQ;
635 case fasta.PLUS_PLUS_TOKEN:
636 return TokenType.PLUS_PLUS;
637 case fasta.PLUS_EQ_TOKEN:
638 return TokenType.PLUS_EQ;
639 case fasta.MINUS_MINUS_TOKEN:
640 return TokenType.MINUS_MINUS;
641 case fasta.MINUS_EQ_TOKEN:
642 return TokenType.MINUS_EQ;
643 case fasta.TILDE_SLASH_EQ_TOKEN:
644 return TokenType.TILDE_SLASH_EQ;
645 case fasta.TILDE_SLASH_TOKEN:
646 return TokenType.TILDE_SLASH;
647 case fasta.PERCENT_EQ_TOKEN:
648 return TokenType.PERCENT_EQ;
649 case fasta.GT_GT_TOKEN:
650 return TokenType.GT_GT;
651 case fasta.CARET_EQ_TOKEN:
652 return TokenType.CARET_EQ;
653 case fasta.COMMENT_TOKEN:
654 // TODO(paulberry,ahe): how to distinguish multi-line from
655 // single-line comments? Causes a failure in test_comment_single().
ahe 2017/02/06 11:01:20 I'd just look at the first two characters of the c
Paul Berry 2017/02/06 13:46:54 Ok. I'll make a follow-up CL that adjusts this co
656 return TokenType.MULTI_LINE_COMMENT;
657 case fasta.STRING_INTERPOLATION_IDENTIFIER_TOKEN:
658 return TokenType.STRING_INTERPOLATION_IDENTIFIER;
659 case fasta.QUESTION_PERIOD_TOKEN:
660 return TokenType.QUESTION_PERIOD;
661 case fasta.QUESTION_QUESTION_TOKEN:
662 return TokenType.QUESTION_QUESTION;
663 case fasta.QUESTION_QUESTION_EQ_TOKEN:
664 return TokenType.QUESTION_QUESTION_EQ;
665 default:
666 throw new UnimplementedError('$kind');
667 }
668 }
669 }
670
671 abstract class ScannerTestBase {
117 void fail_incomplete_string_interpolation() { 672 void fail_incomplete_string_interpolation() {
118 // https://code.google.com/p/dart/issues/detail?id=18073 673 // https://code.google.com/p/dart/issues/detail?id=18073
119 _assertErrorAndTokens( 674 _assertErrorAndTokens(
120 ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 9, "\"foo \${bar", [ 675 ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 9, "\"foo \${bar", [
121 new StringToken(TokenType.STRING, "\"foo ", 0), 676 new StringToken(TokenType.STRING, "\"foo ", 0),
122 new StringToken(TokenType.STRING_INTERPOLATION_EXPRESSION, "\${", 5), 677 new StringToken(TokenType.STRING_INTERPOLATION_EXPRESSION, "\${", 5),
123 new StringToken(TokenType.IDENTIFIER, "bar", 7) 678 new StringToken(TokenType.IDENTIFIER, "bar", 7)
124 ]); 679 ]);
125 } 680 }
126 681
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 void test_comment_generic_method_type_list() { 778 void test_comment_generic_method_type_list() {
224 _assertComment(TokenType.MULTI_LINE_COMMENT, "/*<comment>*/"); 779 _assertComment(TokenType.MULTI_LINE_COMMENT, "/*<comment>*/");
225 _assertComment(TokenType.GENERIC_METHOD_TYPE_LIST, "/*<comment>*/", 780 _assertComment(TokenType.GENERIC_METHOD_TYPE_LIST, "/*<comment>*/",
226 genericMethodComments: true); 781 genericMethodComments: true);
227 } 782 }
228 783
229 void test_comment_multi() { 784 void test_comment_multi() {
230 _assertComment(TokenType.MULTI_LINE_COMMENT, "/* comment */"); 785 _assertComment(TokenType.MULTI_LINE_COMMENT, "/* comment */");
231 } 786 }
232 787
788 void test_comment_multi_consecutive_2() {
Paul Berry 2017/02/03 23:10:36 Note: during this process I discovered that consec
789 Token token = _scan("/* x */ /* y */ z");
790 expect(token.type, TokenType.IDENTIFIER);
791 expect(token.precedingComments, isNotNull);
792 expect(token.precedingComments.value(), "/* x */");
793 expect(token.precedingComments.previous, isNull);
794 expect(token.precedingComments.next, isNotNull);
795 expect(token.precedingComments.next.value(), "/* y */");
796 expect(
797 token.precedingComments.next.previous, same(token.precedingComments));
798 expect(token.precedingComments.next.next, isNull);
799 }
800
801 void test_comment_multi_consecutive_3() {
802 Token token = _scan("/* x */ /* y */ /* z */ a");
803 expect(token.type, TokenType.IDENTIFIER);
804 expect(token.precedingComments, isNotNull);
805 expect(token.precedingComments.value(), "/* x */");
806 expect(token.precedingComments.previous, isNull);
807 expect(token.precedingComments.next, isNotNull);
808 expect(token.precedingComments.next.value(), "/* y */");
809 expect(
810 token.precedingComments.next.previous, same(token.precedingComments));
811 expect(token.precedingComments.next.next, isNotNull);
812 expect(token.precedingComments.next.next.value(), "/* z */");
813 expect(token.precedingComments.next.next.previous,
814 same(token.precedingComments.next));
815 expect(token.precedingComments.next.next.next, isNull);
816 }
817
233 void test_comment_multi_lineEnds() { 818 void test_comment_multi_lineEnds() {
234 String code = r''' 819 String code = r'''
235 /** 820 /**
236 * aa 821 * aa
237 * bbb 822 * bbb
238 * c 823 * c
239 */'''; 824 */''';
240 _ErrorListener listener = new _ErrorListener(); 825 _ErrorListener listener = new _ErrorListener();
241 Scanner scanner = new _TestScanner(new CharSequenceReader(code), listener); 826 Scanner scanner = new _TestScanner(new CharSequenceReader(code), listener);
242 scanner.tokenize(); 827 scanner.tokenize();
(...skipping 899 matching lines...) Expand 10 before | Expand all | Expand 10 after
1142 bool lazyAssignmentOperators: false}) { 1727 bool lazyAssignmentOperators: false}) {
1143 _ErrorListener listener = new _ErrorListener(); 1728 _ErrorListener listener = new _ErrorListener();
1144 Token token = _scanWithListener(source, listener, 1729 Token token = _scanWithListener(source, listener,
1145 genericMethodComments: genericMethodComments, 1730 genericMethodComments: genericMethodComments,
1146 lazyAssignmentOperators: lazyAssignmentOperators); 1731 lazyAssignmentOperators: lazyAssignmentOperators);
1147 listener.assertNoErrors(); 1732 listener.assertNoErrors();
1148 return token; 1733 return token;
1149 } 1734 }
1150 1735
1151 Token _scanWithListener(String source, _ErrorListener listener, 1736 Token _scanWithListener(String source, _ErrorListener listener,
1152 {bool genericMethodComments: false, 1737 {bool genericMethodComments: false, bool lazyAssignmentOperators: false});
1153 bool lazyAssignmentOperators: false}) {
1154 Scanner scanner =
1155 new _TestScanner(new CharSequenceReader(source), listener);
1156 scanner.scanGenericMethodComments = genericMethodComments;
1157 scanner.scanLazyAssignmentOperators = lazyAssignmentOperators;
1158 return scanner.tokenize();
1159 }
1160 } 1738 }
1161 1739
1162 @reflectiveTest 1740 @reflectiveTest
1163 class TokenTypeTest { 1741 class TokenTypeTest {
1164 void test_isOperator() { 1742 void test_isOperator() {
1165 expect(TokenType.AMPERSAND.isOperator, isTrue); 1743 expect(TokenType.AMPERSAND.isOperator, isTrue);
1166 expect(TokenType.AMPERSAND_AMPERSAND.isOperator, isTrue); 1744 expect(TokenType.AMPERSAND_AMPERSAND.isOperator, isTrue);
1167 expect(TokenType.AMPERSAND_EQ.isOperator, isTrue); 1745 expect(TokenType.AMPERSAND_EQ.isOperator, isTrue);
1168 expect(TokenType.BANG.isOperator, isTrue); 1746 expect(TokenType.BANG.isOperator, isTrue);
1169 expect(TokenType.BANG_EQ.isOperator, isTrue); 1747 expect(TokenType.BANG_EQ.isOperator, isTrue);
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
1289 _TestScanner(CharacterReader reader, [this.listener]) : super(reader); 1867 _TestScanner(CharacterReader reader, [this.listener]) : super(reader);
1290 1868
1291 @override 1869 @override
1292 void reportError( 1870 void reportError(
1293 ScannerErrorCode errorCode, int offset, List<Object> arguments) { 1871 ScannerErrorCode errorCode, int offset, List<Object> arguments) {
1294 if (listener != null) { 1872 if (listener != null) {
1295 listener.errors.add(new _TestError(offset, 1, errorCode, arguments)); 1873 listener.errors.add(new _TestError(offset, 1, errorCode, arguments));
1296 } 1874 }
1297 } 1875 }
1298 } 1876 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698