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

Side by Side Diff: pkg/front_end/test/scanner_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 | « pkg/front_end/test/scanner_fasta_test.dart ('k') | 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;
12 import 'package:front_end/src/scanner/errors.dart'; 7 import 'package:front_end/src/scanner/errors.dart';
13 import 'package:front_end/src/scanner/reader.dart'; 8 import 'package:front_end/src/scanner/reader.dart';
14 import 'package:front_end/src/scanner/scanner.dart'; 9 import 'package:front_end/src/scanner/scanner.dart';
15 import 'package:front_end/src/scanner/token.dart'; 10 import 'package:front_end/src/scanner/token.dart';
16 import 'package:test/test.dart'; 11 import 'package:test/test.dart';
17 import 'package:test_reflective_loader/test_reflective_loader.dart'; 12 import 'package:test_reflective_loader/test_reflective_loader.dart';
18 13
19 main() { 14 main() {
20 defineReflectiveSuite(() { 15 defineReflectiveSuite(() {
21 defineReflectiveTests(CharSequenceReaderTest); 16 defineReflectiveTests(CharSequenceReaderTest);
22 defineReflectiveTests(KeywordStateTest); 17 defineReflectiveTests(KeywordStateTest);
23 defineReflectiveTests(ScannerTest); 18 defineReflectiveTests(ScannerTest);
24 defineReflectiveTests(ScannerTest_Fasta);
25 defineReflectiveTests(TokenTypeTest); 19 defineReflectiveTests(TokenTypeTest);
26 }); 20 });
27 } 21 }
28 22
29 @reflectiveTest 23 @reflectiveTest
30 class CharSequenceReaderTest { 24 class CharSequenceReaderTest {
31 void test_advance() { 25 void test_advance() {
32 CharSequenceReader reader = new CharSequenceReader("x"); 26 CharSequenceReader reader = new CharSequenceReader("x");
33 expect(reader.advance(), 0x78); 27 expect(reader.advance(), 0x78);
34 expect(reader.advance(), -1); 28 expect(reader.advance(), -1);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 expect(reader.peek(), -1); 61 expect(reader.peek(), -1);
68 } 62 }
69 63
70 void test_setOffset() { 64 void test_setOffset() {
71 CharSequenceReader reader = new CharSequenceReader("xyz"); 65 CharSequenceReader reader = new CharSequenceReader("xyz");
72 reader.offset = 2; 66 reader.offset = 2;
73 expect(reader.offset, 2); 67 expect(reader.offset, 2);
74 } 68 }
75 } 69 }
76 70
71 class ErrorListener {
72 final errors = <TestError>[];
73
74 void assertErrors(List<TestError> expectedErrors) {
75 expect(errors, unorderedEquals(expectedErrors));
76 }
77
78 void assertNoErrors() {
79 assertErrors([]);
80 }
81 }
82
77 @reflectiveTest 83 @reflectiveTest
78 class KeywordStateTest { 84 class KeywordStateTest {
79 void test_KeywordState() { 85 void test_KeywordState() {
80 // 86 //
81 // Generate the test data to be scanned. 87 // Generate the test data to be scanned.
82 // 88 //
83 List<Keyword> keywords = Keyword.values; 89 List<Keyword> keywords = Keyword.values;
84 int keywordCount = keywords.length; 90 int keywordCount = keywords.length;
85 List<String> textToTest = new List<String>(keywordCount * 3); 91 List<String> textToTest = new List<String>(keywordCount * 3);
86 for (int i = 0; i < keywordCount; i++) { 92 for (int i = 0; i < keywordCount; i++) {
(...skipping 27 matching lines...) Expand all
114 // keyword.substring(0, keyword.length() - 1) 120 // keyword.substring(0, keyword.length() - 1)
115 expect(state, isNotNull); 121 expect(state, isNotNull);
116 } 122 }
117 } 123 }
118 } 124 }
119 } 125 }
120 126
121 @reflectiveTest 127 @reflectiveTest
122 class ScannerTest extends ScannerTestBase { 128 class ScannerTest extends ScannerTestBase {
123 @override 129 @override
124 @failingTest 130 Token scanWithListener(String source, ErrorListener listener,
125 void test_incomplete_string_interpolation() {
126 super.test_incomplete_string_interpolation();
127 }
128
129 @override
130 Token _scanWithListener(String source, _ErrorListener listener,
131 {bool genericMethodComments: false, 131 {bool genericMethodComments: false,
132 bool lazyAssignmentOperators: false}) { 132 bool lazyAssignmentOperators: false}) {
133 Scanner scanner = 133 Scanner scanner =
134 new _TestScanner(new CharSequenceReader(source), listener); 134 new _TestScanner(new CharSequenceReader(source), listener);
135 scanner.scanGenericMethodComments = genericMethodComments; 135 scanner.scanGenericMethodComments = genericMethodComments;
136 scanner.scanLazyAssignmentOperators = lazyAssignmentOperators; 136 scanner.scanLazyAssignmentOperators = lazyAssignmentOperators;
137 return scanner.tokenize(); 137 return scanner.tokenize();
138 } 138 }
139 }
140
141 @reflectiveTest
142 class ScannerTest_Fasta extends ScannerTestBase {
143 final _keywordMap = {
144 "assert": Keyword.ASSERT,
145 "break": Keyword.BREAK,
146 "case": Keyword.CASE,
147 "catch": Keyword.CATCH,
148 "class": Keyword.CLASS,
149 "const": Keyword.CONST,
150 "continue": Keyword.CONTINUE,
151 "default": Keyword.DEFAULT,
152 "do": Keyword.DO,
153 "else": Keyword.ELSE,
154 "enum": Keyword.ENUM,
155 "extends": Keyword.EXTENDS,
156 "false": Keyword.FALSE,
157 "final": Keyword.FINAL,
158 "finally": Keyword.FINALLY,
159 "for": Keyword.FOR,
160 "if": Keyword.IF,
161 "in": Keyword.IN,
162 "new": Keyword.NEW,
163 "null": Keyword.NULL,
164 "rethrow": Keyword.RETHROW,
165 "return": Keyword.RETURN,
166 "super": Keyword.SUPER,
167 "switch": Keyword.SWITCH,
168 "this": Keyword.THIS,
169 "throw": Keyword.THROW,
170 "true": Keyword.TRUE,
171 "try": Keyword.TRY,
172 "var": Keyword.VAR,
173 "void": Keyword.VOID,
174 "while": Keyword.WHILE,
175 "with": Keyword.WITH,
176 "is": Keyword.IS,
177 "abstract": Keyword.ABSTRACT,
178 "as": Keyword.AS,
179 "covariant": Keyword.COVARIANT,
180 "dynamic": Keyword.DYNAMIC,
181 "export": Keyword.EXPORT,
182 "external": Keyword.EXTERNAL,
183 "factory": Keyword.FACTORY,
184 "get": Keyword.GET,
185 "implements": Keyword.IMPLEMENTS,
186 "import": Keyword.IMPORT,
187 "library": Keyword.LIBRARY,
188 "operator": Keyword.OPERATOR,
189 "part": Keyword.PART,
190 "set": Keyword.SET,
191 "static": Keyword.STATIC,
192 "typedef": Keyword.TYPEDEF,
193 "deferred": Keyword.DEFERRED,
194 };
195
196 @override
197 @failingTest
198 void test_ampersand_ampersand_eq() {
199 // TODO(paulberry,ahe): Fasta doesn't support `&&=` yet
200 super.test_ampersand_ampersand_eq();
201 }
202 139
203 @override 140 @override
204 @failingTest 141 @failingTest
205 void test_bar_bar_eq() { 142 void test_incomplete_string_interpolation() {
206 // TODO(paulberry,ahe): Fasta doesn't support `||=` yet 143 super.test_incomplete_string_interpolation();
207 super.test_bar_bar_eq();
208 }
209
210 @override
211 @failingTest
212 void test_comment_generic_method_type_assign() {
213 // TODO(paulberry,ahe): Fasta doesn't support generic method comment syntax.
214 super.test_comment_generic_method_type_assign();
215 }
216
217 @override
218 @failingTest
219 void test_comment_generic_method_type_list() {
220 // TODO(paulberry,ahe): Fasta doesn't support generic method comment syntax.
221 super.test_comment_generic_method_type_list();
222 }
223
224 @override
225 @failingTest
226 void test_index() {
227 // TODO(paulberry,ahe): "[]" should be parsed as a single token.
228 super.test_index();
229 }
230
231 @override
232 @failingTest
233 void test_index_eq() {
234 // TODO(paulberry,ahe): "[]=" should be parsed as a single token.
235 super.test_index_eq();
236 }
237
238 @override
239 @failingTest
240 void test_scriptTag_withArgs() {
241 // TODO(paulberry,ahe): script tags are needed by analyzer.
242 super.test_scriptTag_withArgs();
243 }
244
245 @override
246 @failingTest
247 void test_scriptTag_withoutSpace() {
248 // TODO(paulberry,ahe): script tags are needed by analyzer.
249 super.test_scriptTag_withoutSpace();
250 }
251
252 @override
253 @failingTest
254 void test_scriptTag_withSpace() {
255 // TODO(paulberry,ahe): script tags are needed by analyzer.
256 super.test_scriptTag_withSpace();
257 }
258
259 @override
260 @failingTest
261 void test_string_multi_unterminated() {
262 // TODO(paulberry,ahe): bad error recovery.
263 super.test_string_multi_unterminated();
264 }
265
266 @override
267 @failingTest
268 void test_string_multi_unterminated_interpolation_block() {
269 // TODO(paulberry,ahe): bad error recovery.
270 super.test_string_multi_unterminated_interpolation_block();
271 }
272
273 @override
274 @failingTest
275 void test_string_multi_unterminated_interpolation_identifier() {
276 // TODO(paulberry,ahe): bad error recovery.
277 super.test_string_multi_unterminated_interpolation_identifier();
278 }
279
280 @override
281 @failingTest
282 void test_string_raw_multi_unterminated() {
283 // TODO(paulberry,ahe): bad error recovery.
284 super.test_string_raw_multi_unterminated();
285 }
286
287 @override
288 @failingTest
289 void test_string_raw_simple_unterminated_eof() {
290 // TODO(paulberry,ahe): bad error recovery.
291 super.test_string_raw_simple_unterminated_eof();
292 }
293
294 @override
295 @failingTest
296 void test_string_raw_simple_unterminated_eol() {
297 // TODO(paulberry,ahe): bad error recovery.
298 super.test_string_raw_simple_unterminated_eol();
299 }
300
301 @override
302 @failingTest
303 void test_string_simple_unterminated_eof() {
304 // TODO(paulberry,ahe): bad error recovery.
305 super.test_string_simple_unterminated_eof();
306 }
307
308 @override
309 @failingTest
310 void test_string_simple_unterminated_eol() {
311 // TODO(paulberry,ahe): bad error recovery.
312 super.test_string_simple_unterminated_eol();
313 }
314
315 @override
316 @failingTest
317 void test_string_simple_unterminated_interpolation_block() {
318 // TODO(paulberry,ahe): bad error recovery.
319 super.test_string_simple_unterminated_interpolation_block();
320 }
321
322 @override
323 @failingTest
324 void test_string_simple_unterminated_interpolation_identifier() {
325 // TODO(paulberry,ahe): bad error recovery.
326 super.test_string_simple_unterminated_interpolation_identifier();
327 }
328
329 @override
330 Token _scanWithListener(String source, _ErrorListener listener,
331 {bool genericMethodComments: false,
332 bool lazyAssignmentOperators: false}) {
333 if (genericMethodComments) {
334 // Fasta doesn't support generic method comments.
335 // TODO(paulberry): once the analyzer toolchain no longer needs generic
336 // method comments, remove tests that exercise them.
337 fail('No generic method comment support in Fasta');
338 }
339 // Note: Fasta always supports lazy assignment operators (`&&=` and `||=`),
340 // so we can ignore the `lazyAssignmentOperators` flag.
341 // TODO(paulberry): once lazyAssignmentOperators are fully supported by
342 // Dart, remove this flag.
343 var scanner = new fasta.StringScanner(source, includeComments: true);
344 var token = scanner.tokenize();
345 var analyzerTokenHead = new Token(null, 0);
346 analyzerTokenHead.previous = analyzerTokenHead;
347 var analyzerTokenTail = analyzerTokenHead;
348 // TODO(paulberry,ahe): Fasta includes comments directly in the token
349 // stream, rather than pointing to them via a "precedingComment" pointer, as
350 // analyzer does. This seems like it will complicate parsing and other
351 // operations.
352 CommentToken currentCommentHead;
353 CommentToken currentCommentTail;
354 while (true) {
355 if (scanner.hasErrors && token is fasta.ErrorToken) {
356 var error = _translateErrorToken(token, source.length);
357 if (error != null) {
358 listener.errors.add(error);
359 }
360 } else if (token is fasta.StringToken &&
361 token.info.kind == fasta.COMMENT_TOKEN) {
362 // TODO(paulberry,ahe): It would be nice if the scanner gave us an
363 // easier way to distinguish between the two types of comment.
364 var type = token.value.startsWith('/*')
365 ? TokenType.MULTI_LINE_COMMENT
366 : TokenType.SINGLE_LINE_COMMENT;
367 var translatedToken =
368 new CommentToken(type, token.value, token.charOffset);
369 if (currentCommentHead == null) {
370 currentCommentHead = currentCommentTail = translatedToken;
371 } else {
372 currentCommentTail.setNext(translatedToken);
373 currentCommentTail = translatedToken;
374 }
375 } else {
376 var translatedToken = _translateToken(token, currentCommentHead);
377 translatedToken.setNext(translatedToken);
378 currentCommentHead = currentCommentTail = null;
379 analyzerTokenTail.setNext(translatedToken);
380 translatedToken.previous = analyzerTokenTail;
381 analyzerTokenTail = translatedToken;
382 }
383 if (token.isEof) {
384 return analyzerTokenHead.next;
385 }
386 token = token.next;
387 }
388 }
389
390 _TestError _translateErrorToken(fasta.ErrorToken token, int inputLength) {
391 int charOffset = token.charOffset;
392 // TODO(paulberry,ahe): why is endOffset sometimes null?
393 int endOffset = token.endOffset ?? charOffset;
394 _TestError _makeError(ScannerErrorCode errorCode, List<Object> arguments) {
395 int errorLength = endOffset - charOffset;
396 if (charOffset == inputLength) {
397 // Analyzer never generates an error message past the end of the input,
398 // since such an error would not be visible in an editor.
399 // TODO(paulberry,ahe): would it make sense to replicate this behavior
400 // in fasta, or move it elsewhere in analyzer?
401 charOffset--;
402 }
403 if (errorLength == 0) {
404 // Analyzer never generates an error message of length zero,
405 // since such an error would not be visible in an editor.
406 // TODO(paulberry,ahe): would it make sense to replicate this behavior
407 // in fasta, or move it elsewhere in analyzer?
408 errorLength = 1;
409 }
410 return new _TestError(charOffset, errorLength, errorCode, arguments);
411 }
412
413 var errorCode = token.errorCode;
414 switch (errorCode) {
415 case fasta.ErrorKind.UnterminatedString:
416 // TODO(paulberry,ahe): Fasta reports the error location as the entire
417 // string; analyzer expects the end of the string.
418 charOffset = endOffset;
419 return _makeError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, null);
420 case fasta.ErrorKind.UnmatchedToken:
421 return null;
422 case fasta.ErrorKind.UnterminatedComment:
423 // TODO(paulberry,ahe): Fasta reports the error location as the entire
424 // comment; analyzer expects the end of the comment.
425 charOffset = endOffset;
426 return _makeError(
427 ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT, null);
428 case fasta.ErrorKind.MissingExponent:
429 // TODO(paulberry,ahe): Fasta reports the error location as the entire
430 // number; analyzer expects the end of the number.
431 charOffset = endOffset;
432 return _makeError(ScannerErrorCode.MISSING_DIGIT, null);
433 case fasta.ErrorKind.ExpectedHexDigit:
434 // TODO(paulberry,ahe): Fasta reports the error location as the entire
435 // number; analyzer expects the end of the number.
436 charOffset = endOffset;
437 return _makeError(ScannerErrorCode.MISSING_HEX_DIGIT, null);
438 case fasta.ErrorKind.NonAsciiIdentifier:
439 case fasta.ErrorKind.NonAsciiWhitespace:
440 return _makeError(
441 ScannerErrorCode.ILLEGAL_CHARACTER, [token.character]);
442 case fasta.ErrorKind.UnexpectedDollarInString:
443 return null;
444 default:
445 throw new UnimplementedError('$errorCode');
446 }
447 }
448
449 Keyword _translateKeyword(String syntax) =>
450 _keywordMap[syntax] ?? (throw new UnimplementedError('$syntax'));
451
452 Token _translateToken(fasta.Token token, CommentToken comment) {
453 var type = _translateTokenInfoKind(token.info.kind);
454 int offset = token.charOffset;
455 Token makeStringToken(String value) {
456 if (comment == null) {
457 return new StringToken(type, value, offset);
458 } else {
459 return new StringTokenWithComment(type, value, offset, comment);
460 }
461 }
462
463 Token makeKeywordToken(Keyword keyword) {
464 if (comment == null) {
465 return new KeywordToken(keyword, offset);
466 } else {
467 return new KeywordTokenWithComment(keyword, offset, comment);
468 }
469 }
470
471 Token makeBeginToken() {
472 if (comment == null) {
473 return new BeginToken(type, offset);
474 } else {
475 return new BeginTokenWithComment(type, offset, comment);
476 }
477 }
478
479 if (token is fasta.StringToken) {
480 return makeStringToken(token.value);
481 } else if (token is fasta.KeywordToken) {
482 return makeKeywordToken(_translateKeyword(token.keyword.syntax));
483 } else if (token is fasta.SymbolToken) {
484 if (token is fasta.BeginGroupToken) {
485 if (type == TokenType.LT) {
486 return makeStringToken(token.value);
487 } else {
488 return makeBeginToken();
489 }
490 } else {
491 return makeStringToken(token.value);
492 }
493 }
494 throw new UnimplementedError('${token.runtimeType}');
495 }
496
497 TokenType _translateTokenInfoKind(int kind) {
498 switch (kind) {
499 case fasta.EOF_TOKEN:
500 return TokenType.EOF;
501 case fasta.KEYWORD_TOKEN:
502 return TokenType.KEYWORD;
503 case fasta.IDENTIFIER_TOKEN:
504 return TokenType.IDENTIFIER;
505 case fasta.BAD_INPUT_TOKEN:
506 return TokenType.STRING;
507 case fasta.DOUBLE_TOKEN:
508 return TokenType.DOUBLE;
509 case fasta.INT_TOKEN:
510 return TokenType.INT;
511 case fasta.HEXADECIMAL_TOKEN:
512 return TokenType.HEXADECIMAL;
513 case fasta.STRING_TOKEN:
514 return TokenType.STRING;
515 case fasta.AMPERSAND_TOKEN:
516 return TokenType.AMPERSAND;
517 case fasta.BACKPING_TOKEN:
518 return TokenType.BACKPING;
519 case fasta.BACKSLASH_TOKEN:
520 return TokenType.BACKSLASH;
521 case fasta.BANG_TOKEN:
522 return TokenType.BANG;
523 case fasta.BAR_TOKEN:
524 return TokenType.BAR;
525 case fasta.COLON_TOKEN:
526 return TokenType.COLON;
527 case fasta.COMMA_TOKEN:
528 return TokenType.COMMA;
529 case fasta.EQ_TOKEN:
530 return TokenType.EQ;
531 case fasta.GT_TOKEN:
532 return TokenType.GT;
533 case fasta.HASH_TOKEN:
534 return TokenType.HASH;
535 case fasta.OPEN_CURLY_BRACKET_TOKEN:
536 return TokenType.OPEN_CURLY_BRACKET;
537 case fasta.OPEN_SQUARE_BRACKET_TOKEN:
538 return TokenType.OPEN_SQUARE_BRACKET;
539 case fasta.OPEN_PAREN_TOKEN:
540 return TokenType.OPEN_PAREN;
541 case fasta.LT_TOKEN:
542 return TokenType.LT;
543 case fasta.MINUS_TOKEN:
544 return TokenType.MINUS;
545 case fasta.PERIOD_TOKEN:
546 return TokenType.PERIOD;
547 case fasta.PLUS_TOKEN:
548 return TokenType.PLUS;
549 case fasta.QUESTION_TOKEN:
550 return TokenType.QUESTION;
551 case fasta.AT_TOKEN:
552 return TokenType.AT;
553 case fasta.CLOSE_CURLY_BRACKET_TOKEN:
554 return TokenType.CLOSE_CURLY_BRACKET;
555 case fasta.CLOSE_SQUARE_BRACKET_TOKEN:
556 return TokenType.CLOSE_SQUARE_BRACKET;
557 case fasta.CLOSE_PAREN_TOKEN:
558 return TokenType.CLOSE_PAREN;
559 case fasta.SEMICOLON_TOKEN:
560 return TokenType.SEMICOLON;
561 case fasta.SLASH_TOKEN:
562 return TokenType.SLASH;
563 case fasta.TILDE_TOKEN:
564 return TokenType.TILDE;
565 case fasta.STAR_TOKEN:
566 return TokenType.STAR;
567 case fasta.PERCENT_TOKEN:
568 return TokenType.PERCENT;
569 case fasta.CARET_TOKEN:
570 return TokenType.CARET;
571 case fasta.STRING_INTERPOLATION_TOKEN:
572 return TokenType.STRING_INTERPOLATION_EXPRESSION;
573 case fasta.LT_EQ_TOKEN:
574 return TokenType.LT_EQ;
575 case fasta.FUNCTION_TOKEN:
576 return TokenType.FUNCTION;
577 case fasta.SLASH_EQ_TOKEN:
578 return TokenType.SLASH_EQ;
579 case fasta.PERIOD_PERIOD_PERIOD_TOKEN:
580 return TokenType.PERIOD_PERIOD_PERIOD;
581 case fasta.PERIOD_PERIOD_TOKEN:
582 return TokenType.PERIOD_PERIOD;
583 case fasta.EQ_EQ_EQ_TOKEN:
584 // TODO(paulberry,ahe): what is this?
585 throw new UnimplementedError();
586 case fasta.EQ_EQ_TOKEN:
587 return TokenType.EQ_EQ;
588 case fasta.LT_LT_EQ_TOKEN:
589 return TokenType.LT_LT_EQ;
590 case fasta.LT_LT_TOKEN:
591 return TokenType.LT_LT;
592 case fasta.GT_EQ_TOKEN:
593 return TokenType.GT_EQ;
594 case fasta.GT_GT_EQ_TOKEN:
595 return TokenType.GT_GT_EQ;
596 case fasta.INDEX_EQ_TOKEN:
597 return TokenType.INDEX_EQ;
598 case fasta.INDEX_TOKEN:
599 return TokenType.INDEX;
600 case fasta.BANG_EQ_EQ_TOKEN:
601 // TODO(paulberry,ahe): what is this?
602 throw new UnimplementedError();
603 case fasta.BANG_EQ_TOKEN:
604 return TokenType.BANG_EQ;
605 case fasta.AMPERSAND_AMPERSAND_TOKEN:
606 return TokenType.AMPERSAND_AMPERSAND;
607 case fasta.AMPERSAND_EQ_TOKEN:
608 return TokenType.AMPERSAND_EQ;
609 case fasta.BAR_BAR_TOKEN:
610 return TokenType.BAR_BAR;
611 case fasta.BAR_EQ_TOKEN:
612 return TokenType.BAR_EQ;
613 case fasta.STAR_EQ_TOKEN:
614 return TokenType.STAR_EQ;
615 case fasta.PLUS_PLUS_TOKEN:
616 return TokenType.PLUS_PLUS;
617 case fasta.PLUS_EQ_TOKEN:
618 return TokenType.PLUS_EQ;
619 case fasta.MINUS_MINUS_TOKEN:
620 return TokenType.MINUS_MINUS;
621 case fasta.MINUS_EQ_TOKEN:
622 return TokenType.MINUS_EQ;
623 case fasta.TILDE_SLASH_EQ_TOKEN:
624 return TokenType.TILDE_SLASH_EQ;
625 case fasta.TILDE_SLASH_TOKEN:
626 return TokenType.TILDE_SLASH;
627 case fasta.PERCENT_EQ_TOKEN:
628 return TokenType.PERCENT_EQ;
629 case fasta.GT_GT_TOKEN:
630 return TokenType.GT_GT;
631 case fasta.CARET_EQ_TOKEN:
632 return TokenType.CARET_EQ;
633 case fasta.STRING_INTERPOLATION_IDENTIFIER_TOKEN:
634 return TokenType.STRING_INTERPOLATION_IDENTIFIER;
635 case fasta.QUESTION_PERIOD_TOKEN:
636 return TokenType.QUESTION_PERIOD;
637 case fasta.QUESTION_QUESTION_TOKEN:
638 return TokenType.QUESTION_QUESTION;
639 case fasta.QUESTION_QUESTION_EQ_TOKEN:
640 return TokenType.QUESTION_QUESTION_EQ;
641 default:
642 throw new UnimplementedError('$kind');
643 }
644 } 144 }
645 } 145 }
646 146
647 abstract class ScannerTestBase { 147 abstract class ScannerTestBase {
148 Token scanWithListener(String source, ErrorListener listener,
149 {bool genericMethodComments: false, bool lazyAssignmentOperators: false});
150
648 void test_ampersand() { 151 void test_ampersand() {
649 _assertToken(TokenType.AMPERSAND, "&"); 152 _assertToken(TokenType.AMPERSAND, "&");
650 } 153 }
651 154
652 void test_ampersand_ampersand() { 155 void test_ampersand_ampersand() {
653 _assertToken(TokenType.AMPERSAND_AMPERSAND, "&&"); 156 _assertToken(TokenType.AMPERSAND_AMPERSAND, "&&");
654 } 157 }
655 158
656 void test_ampersand_ampersand_eq() { 159 void test_ampersand_ampersand_eq() {
657 _assertToken(TokenType.AMPERSAND_AMPERSAND_EQ, "&&=", 160 _assertToken(TokenType.AMPERSAND_AMPERSAND_EQ, "&&=",
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
781 expect(token.precedingComments.next.next.next, isNull); 284 expect(token.precedingComments.next.next.next, isNull);
782 } 285 }
783 286
784 void test_comment_multi_lineEnds() { 287 void test_comment_multi_lineEnds() {
785 String code = r''' 288 String code = r'''
786 /** 289 /**
787 * aa 290 * aa
788 * bbb 291 * bbb
789 * c 292 * c
790 */'''; 293 */''';
791 _ErrorListener listener = new _ErrorListener(); 294 ErrorListener listener = new ErrorListener();
792 Scanner scanner = new _TestScanner(new CharSequenceReader(code), listener); 295 Scanner scanner = new _TestScanner(new CharSequenceReader(code), listener);
793 scanner.tokenize(); 296 scanner.tokenize();
794 expect( 297 expect(
795 scanner.lineStarts, 298 scanner.lineStarts,
796 equals(<int>[ 299 equals(<int>[
797 code.indexOf('/**'), 300 code.indexOf('/**'),
798 code.indexOf(' * aa'), 301 code.indexOf(' * aa'),
799 code.indexOf(' * bbb'), 302 code.indexOf(' * bbb'),
800 code.indexOf(' * c'), 303 code.indexOf(' * c'),
801 code.indexOf(' */') 304 code.indexOf(' */')
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after
1245 void test_scriptTag_withSpace() { 748 void test_scriptTag_withSpace() {
1246 _assertToken(TokenType.SCRIPT_TAG, "#! /bin/dart"); 749 _assertToken(TokenType.SCRIPT_TAG, "#! /bin/dart");
1247 } 750 }
1248 751
1249 void test_semicolon() { 752 void test_semicolon() {
1250 _assertToken(TokenType.SEMICOLON, ";"); 753 _assertToken(TokenType.SEMICOLON, ";");
1251 } 754 }
1252 755
1253 void test_setSourceStart() { 756 void test_setSourceStart() {
1254 int offsetDelta = 42; 757 int offsetDelta = 42;
1255 _ErrorListener listener = new _ErrorListener(); 758 ErrorListener listener = new ErrorListener();
1256 Scanner scanner = 759 Scanner scanner =
1257 new _TestScanner(new SubSequenceReader("a", offsetDelta), listener); 760 new _TestScanner(new SubSequenceReader("a", offsetDelta), listener);
1258 scanner.setSourceStart(3, 9); 761 scanner.setSourceStart(3, 9);
1259 scanner.tokenize(); 762 scanner.tokenize();
1260 List<int> lineStarts = scanner.lineStarts; 763 List<int> lineStarts = scanner.lineStarts;
1261 expect(lineStarts, isNotNull); 764 expect(lineStarts, isNotNull);
1262 expect(lineStarts.length, 3); 765 expect(lineStarts.length, 3);
1263 expect(lineStarts[2], 33); 766 expect(lineStarts[2], 33);
1264 } 767 }
1265 768
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
1516 1019
1517 void test_tilde_slash() { 1020 void test_tilde_slash() {
1518 _assertToken(TokenType.TILDE_SLASH, "~/"); 1021 _assertToken(TokenType.TILDE_SLASH, "~/");
1519 } 1022 }
1520 1023
1521 void test_tilde_slash_eq() { 1024 void test_tilde_slash_eq() {
1522 _assertToken(TokenType.TILDE_SLASH_EQ, "~/="); 1025 _assertToken(TokenType.TILDE_SLASH_EQ, "~/=");
1523 } 1026 }
1524 1027
1525 void test_unclosedPairInInterpolation() { 1028 void test_unclosedPairInInterpolation() {
1526 _ErrorListener listener = new _ErrorListener(); 1029 ErrorListener listener = new ErrorListener();
1527 _scanWithListener("'\${(}'", listener); 1030 scanWithListener("'\${(}'", listener);
1528 } 1031 }
1529 1032
1530 void _assertComment(TokenType commentType, String source, 1033 void _assertComment(TokenType commentType, String source,
1531 {bool genericMethodComments: false}) { 1034 {bool genericMethodComments: false}) {
1532 // 1035 //
1533 // Test without a trailing end-of-line marker 1036 // Test without a trailing end-of-line marker
1534 // 1037 //
1535 Token token = _scan(source, genericMethodComments: genericMethodComments); 1038 Token token = _scan(source, genericMethodComments: genericMethodComments);
1536 expect(token, isNotNull); 1039 expect(token, isNotNull);
1537 expect(token.type, TokenType.EOF); 1040 expect(token.type, TokenType.EOF);
(...skipping 21 matching lines...) Expand all
1559 * Assert that scanning the given [source] produces an error with the given 1062 * Assert that scanning the given [source] produces an error with the given
1560 * code. 1063 * code.
1561 * 1064 *
1562 * [expectedError] the error that should be produced 1065 * [expectedError] the error that should be produced
1563 * [expectedOffset] the string offset that should be associated with the error 1066 * [expectedOffset] the string offset that should be associated with the error
1564 * [source] the source to be scanned to produce the error 1067 * [source] the source to be scanned to produce the error
1565 */ 1068 */
1566 void _assertError( 1069 void _assertError(
1567 ScannerErrorCode expectedError, int expectedOffset, String source, 1070 ScannerErrorCode expectedError, int expectedOffset, String source,
1568 [List<Object> arguments]) { 1071 [List<Object> arguments]) {
1569 _ErrorListener listener = new _ErrorListener(); 1072 ErrorListener listener = new ErrorListener();
1570 _scanWithListener(source, listener); 1073 scanWithListener(source, listener);
1571 listener.assertErrors( 1074 listener.assertErrors(
1572 [new _TestError(expectedOffset, 1, expectedError, arguments)]); 1075 [new TestError(expectedOffset, 1, expectedError, arguments)]);
1573 } 1076 }
1574 1077
1575 /** 1078 /**
1576 * Assert that scanning the given [source] produces an error with the given 1079 * Assert that scanning the given [source] produces an error with the given
1577 * code, and also produces the given tokens. 1080 * code, and also produces the given tokens.
1578 * 1081 *
1579 * [expectedError] the error that should be produced 1082 * [expectedError] the error that should be produced
1580 * [expectedOffset] the string offset that should be associated with the error 1083 * [expectedOffset] the string offset that should be associated with the error
1581 * [source] the source to be scanned to produce the error 1084 * [source] the source to be scanned to produce the error
1582 * [expectedTokens] the tokens that are expected to be in the source 1085 * [expectedTokens] the tokens that are expected to be in the source
1583 */ 1086 */
1584 void _assertErrorAndTokens(ScannerErrorCode expectedError, int expectedOffset, 1087 void _assertErrorAndTokens(ScannerErrorCode expectedError, int expectedOffset,
1585 String source, List<Token> expectedTokens) { 1088 String source, List<Token> expectedTokens) {
1586 _ErrorListener listener = new _ErrorListener(); 1089 ErrorListener listener = new ErrorListener();
1587 Token token = _scanWithListener(source, listener); 1090 Token token = scanWithListener(source, listener);
1588 listener 1091 listener
1589 .assertErrors([new _TestError(expectedOffset, 1, expectedError, null)]); 1092 .assertErrors([new TestError(expectedOffset, 1, expectedError, null)]);
1590 _checkTokens(token, expectedTokens); 1093 _checkTokens(token, expectedTokens);
1591 } 1094 }
1592 1095
1593 /** 1096 /**
1594 * Assert that when scanned the given [source] contains a single keyword token 1097 * Assert that when scanned the given [source] contains a single keyword token
1595 * with the same lexeme as the original source. 1098 * with the same lexeme as the original source.
1596 */ 1099 */
1597 void _assertKeywordToken(String source) { 1100 void _assertKeywordToken(String source) {
1598 Token token = _scan(source); 1101 Token token = _scan(source);
1599 expect(token, isNotNull); 1102 expect(token, isNotNull);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1694 reason: "Wrong lexeme for token $i"); 1197 reason: "Wrong lexeme for token $i");
1695 token = token.next; 1198 token = token.next;
1696 expect(token, isNotNull); 1199 expect(token, isNotNull);
1697 } 1200 }
1698 expect(token.type, TokenType.EOF); 1201 expect(token.type, TokenType.EOF);
1699 } 1202 }
1700 1203
1701 Token _scan(String source, 1204 Token _scan(String source,
1702 {bool genericMethodComments: false, 1205 {bool genericMethodComments: false,
1703 bool lazyAssignmentOperators: false}) { 1206 bool lazyAssignmentOperators: false}) {
1704 _ErrorListener listener = new _ErrorListener(); 1207 ErrorListener listener = new ErrorListener();
1705 Token token = _scanWithListener(source, listener, 1208 Token token = scanWithListener(source, listener,
1706 genericMethodComments: genericMethodComments, 1209 genericMethodComments: genericMethodComments,
1707 lazyAssignmentOperators: lazyAssignmentOperators); 1210 lazyAssignmentOperators: lazyAssignmentOperators);
1708 listener.assertNoErrors(); 1211 listener.assertNoErrors();
1709 return token; 1212 return token;
1710 } 1213 }
1214 }
1711 1215
1712 Token _scanWithListener(String source, _ErrorListener listener, 1216 class TestError {
1713 {bool genericMethodComments: false, bool lazyAssignmentOperators: false}); 1217 final int offset;
1218 final int length;
1219 final ErrorCode errorCode;
1220 final List<Object> arguments;
1221
1222 TestError(this.offset, this.length, this.errorCode, this.arguments);
1223
1224 @override
1225 get hashCode {
1226 var h = new JenkinsSmiHash()..add(offset)..add(length)..add(errorCode);
1227 if (arguments != null) {
1228 for (Object argument in arguments) {
1229 h.add(argument);
1230 }
1231 }
1232 return h.hashCode;
1233 }
1234
1235 @override
1236 operator ==(Object other) {
1237 if (other is TestError &&
1238 offset == other.offset &&
1239 length == other.length &&
1240 errorCode == other.errorCode) {
1241 if (arguments == null) return other.arguments == null;
1242 if (other.arguments == null) return false;
1243 if (arguments.length != other.arguments.length) return false;
1244 for (int i = 0; i < arguments.length; i++) {
1245 if (arguments[i] != other.arguments[i]) return false;
1246 }
1247 return true;
1248 }
1249 return false;
1250 }
1251
1252 @override
1253 toString() {
1254 var end = offset + length;
1255 var argString = arguments == null ? '' : '(${arguments.join(', ')})';
1256 return 'Error($offset..$end, $errorCode$argString)';
1257 }
1714 } 1258 }
1715 1259
1716 @reflectiveTest 1260 @reflectiveTest
1717 class TokenTypeTest { 1261 class TokenTypeTest {
1718 void test_isOperator() { 1262 void test_isOperator() {
1719 expect(TokenType.AMPERSAND.isOperator, isTrue); 1263 expect(TokenType.AMPERSAND.isOperator, isTrue);
1720 expect(TokenType.AMPERSAND_AMPERSAND.isOperator, isTrue); 1264 expect(TokenType.AMPERSAND_AMPERSAND.isOperator, isTrue);
1721 expect(TokenType.AMPERSAND_EQ.isOperator, isTrue); 1265 expect(TokenType.AMPERSAND_EQ.isOperator, isTrue);
1722 expect(TokenType.BANG.isOperator, isTrue); 1266 expect(TokenType.BANG.isOperator, isTrue);
1723 expect(TokenType.BANG_EQ.isOperator, isTrue); 1267 expect(TokenType.BANG_EQ.isOperator, isTrue);
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1774 expect(TokenType.MINUS.isUserDefinableOperator, isTrue); 1318 expect(TokenType.MINUS.isUserDefinableOperator, isTrue);
1775 expect(TokenType.PERCENT.isUserDefinableOperator, isTrue); 1319 expect(TokenType.PERCENT.isUserDefinableOperator, isTrue);
1776 expect(TokenType.PLUS.isUserDefinableOperator, isTrue); 1320 expect(TokenType.PLUS.isUserDefinableOperator, isTrue);
1777 expect(TokenType.SLASH.isUserDefinableOperator, isTrue); 1321 expect(TokenType.SLASH.isUserDefinableOperator, isTrue);
1778 expect(TokenType.STAR.isUserDefinableOperator, isTrue); 1322 expect(TokenType.STAR.isUserDefinableOperator, isTrue);
1779 expect(TokenType.TILDE.isUserDefinableOperator, isTrue); 1323 expect(TokenType.TILDE.isUserDefinableOperator, isTrue);
1780 expect(TokenType.TILDE_SLASH.isUserDefinableOperator, isTrue); 1324 expect(TokenType.TILDE_SLASH.isUserDefinableOperator, isTrue);
1781 } 1325 }
1782 } 1326 }
1783 1327
1784 class _ErrorListener {
1785 final errors = <_TestError>[];
1786
1787 void assertErrors(List<_TestError> expectedErrors) {
1788 expect(errors, unorderedEquals(expectedErrors));
1789 }
1790
1791 void assertNoErrors() {
1792 assertErrors([]);
1793 }
1794 }
1795
1796 class _TestError {
1797 final int offset;
1798 final int length;
1799 final ErrorCode errorCode;
1800 final List<Object> arguments;
1801
1802 _TestError(this.offset, this.length, this.errorCode, this.arguments);
1803
1804 @override
1805 get hashCode {
1806 var h = new JenkinsSmiHash()..add(offset)..add(length)..add(errorCode);
1807 if (arguments != null) {
1808 for (Object argument in arguments) {
1809 h.add(argument);
1810 }
1811 }
1812 return h.hashCode;
1813 }
1814
1815 @override
1816 operator ==(Object other) {
1817 if (other is _TestError &&
1818 offset == other.offset &&
1819 length == other.length &&
1820 errorCode == other.errorCode) {
1821 if (arguments == null) return other.arguments == null;
1822 if (other.arguments == null) return false;
1823 if (arguments.length != other.arguments.length) return false;
1824 for (int i = 0; i < arguments.length; i++) {
1825 if (arguments[i] != other.arguments[i]) return false;
1826 }
1827 return true;
1828 }
1829 return false;
1830 }
1831
1832 @override
1833 toString() {
1834 var end = offset + length;
1835 var argString = arguments == null ? '' : '(${arguments.join(', ')})';
1836 return 'Error($offset..$end, $errorCode$argString)';
1837 }
1838 }
1839
1840 class _TestScanner extends Scanner { 1328 class _TestScanner extends Scanner {
1841 final _ErrorListener listener; 1329 final ErrorListener listener;
1842 1330
1843 _TestScanner(CharacterReader reader, [this.listener]) : super(reader); 1331 _TestScanner(CharacterReader reader, [this.listener]) : super(reader);
1844 1332
1845 @override 1333 @override
1846 void reportError( 1334 void reportError(
1847 ScannerErrorCode errorCode, int offset, List<Object> arguments) { 1335 ScannerErrorCode errorCode, int offset, List<Object> arguments) {
1848 if (listener != null) { 1336 if (listener != null) {
1849 listener.errors.add(new _TestError(offset, 1, errorCode, arguments)); 1337 listener.errors.add(new TestError(offset, 1, errorCode, arguments));
1850 } 1338 }
1851 } 1339 }
1852 } 1340 }
OLDNEW
« no previous file with comments | « pkg/front_end/test/scanner_fasta_test.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698