OLD | NEW |
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/scanner/errors.dart'; | 7 import 'package:front_end/src/scanner/errors.dart'; |
8 import 'package:front_end/src/scanner/reader.dart'; | 8 import 'package:front_end/src/scanner/reader.dart'; |
9 import 'package:front_end/src/scanner/scanner.dart'; | 9 import 'package:front_end/src/scanner/scanner.dart'; |
10 import 'package:front_end/src/scanner/token.dart'; | 10 import 'package:front_end/src/scanner/token.dart'; |
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 _assertError(ScannerErrorCode.ILLEGAL_CHARACTER, 0, "\u0312", [0x312]); | 428 _assertError(ScannerErrorCode.ILLEGAL_CHARACTER, 0, "\u0312", [0x312]); |
429 } | 429 } |
430 | 430 |
431 void test_incomplete_string_interpolation() { | 431 void test_incomplete_string_interpolation() { |
432 // https://code.google.com/p/dart/issues/detail?id=18073 | 432 // https://code.google.com/p/dart/issues/detail?id=18073 |
433 List<Token> expectedTokens = [ | 433 List<Token> expectedTokens = [ |
434 new StringToken(TokenType.STRING, "\"foo ", 0), | 434 new StringToken(TokenType.STRING, "\"foo ", 0), |
435 new StringToken(TokenType.STRING_INTERPOLATION_EXPRESSION, "\${", 5), | 435 new StringToken(TokenType.STRING_INTERPOLATION_EXPRESSION, "\${", 5), |
436 new StringToken(TokenType.IDENTIFIER, "bar", 7), | 436 new StringToken(TokenType.IDENTIFIER, "bar", 7), |
437 ]; | 437 ]; |
| 438 var expectedErrors = [ |
| 439 new TestError(9, ScannerErrorCode.UNTERMINATED_STRING_LITERAL, null), |
| 440 ]; |
438 if (usingFasta) { | 441 if (usingFasta) { |
439 // fasta inserts synthetic closers | 442 // fasta inserts synthetic closers |
440 expectedTokens.addAll([ | 443 expectedTokens.addAll([ |
441 new SyntheticToken(TokenType.CLOSE_CURLY_BRACKET, 10), | 444 new SyntheticToken(TokenType.CLOSE_CURLY_BRACKET, 10), |
442 new SyntheticStringToken(TokenType.STRING, "\"", 10, 0), | 445 new SyntheticStringToken(TokenType.STRING, "\"", 10, 0), |
443 ]); | 446 ]); |
| 447 expectedErrors.addAll([ |
| 448 new TestError(5, ScannerErrorCode.EXPECTED_TOKEN, ['}']), |
| 449 ]); |
444 } else { | 450 } else { |
445 expectedTokens.addAll([ | 451 expectedTokens.addAll([ |
446 new StringToken(TokenType.STRING, "", 10), | 452 new StringToken(TokenType.STRING, "", 10), |
447 ]); | 453 ]); |
448 } | 454 } |
449 _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 9, | 455 ErrorListener listener = new ErrorListener(); |
450 "\"foo \${bar", expectedTokens); | 456 Token token = scanWithListener("\"foo \${bar", listener); |
| 457 listener.assertErrors(expectedErrors); |
| 458 _checkTokens(token, expectedTokens); |
451 } | 459 } |
452 | 460 |
453 void test_index() { | 461 void test_index() { |
454 _assertToken(TokenType.INDEX, "[]"); | 462 _assertToken(TokenType.INDEX, "[]"); |
455 } | 463 } |
456 | 464 |
457 void test_index_eq() { | 465 void test_index_eq() { |
458 _assertToken(TokenType.INDEX_EQ, "[]="); | 466 _assertToken(TokenType.INDEX_EQ, "[]="); |
459 } | 467 } |
460 | 468 |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
712 | 720 |
713 void test_lt_lt() { | 721 void test_lt_lt() { |
714 _assertToken(TokenType.LT_LT, "<<"); | 722 _assertToken(TokenType.LT_LT, "<<"); |
715 } | 723 } |
716 | 724 |
717 void test_lt_lt_eq() { | 725 void test_lt_lt_eq() { |
718 _assertToken(TokenType.LT_LT_EQ, "<<="); | 726 _assertToken(TokenType.LT_LT_EQ, "<<="); |
719 } | 727 } |
720 | 728 |
721 void test_matching_braces() { | 729 void test_matching_braces() { |
722 var openBrace1 = _scan('{1: {2: 3}}') as BeginToken; | 730 BeginToken openBrace1 = _scan('{1: {2: 3}}'); |
723 var one = openBrace1.next; | 731 var one = openBrace1.next; |
724 var colon1 = one.next; | 732 var colon1 = one.next; |
725 var openBrace2 = colon1.next as BeginToken; | 733 BeginToken openBrace2 = colon1.next; |
726 var two = openBrace2.next; | 734 var two = openBrace2.next; |
727 var colon2 = two.next; | 735 var colon2 = two.next; |
728 var three = colon2.next; | 736 var three = colon2.next; |
729 var closeBrace1 = three.next; | 737 var closeBrace1 = three.next; |
730 var closeBrace2 = closeBrace1.next; | 738 var closeBrace2 = closeBrace1.next; |
731 expect(closeBrace2.next.type, TokenType.EOF); | 739 expect(closeBrace2.next.type, TokenType.EOF); |
732 expect(openBrace1.endToken, same(closeBrace2)); | 740 expect(openBrace1.endToken, same(closeBrace2)); |
733 expect(openBrace2.endToken, same(closeBrace1)); | 741 expect(openBrace2.endToken, same(closeBrace1)); |
734 } | 742 } |
735 | 743 |
736 void test_matching_brackets() { | 744 void test_matching_brackets() { |
737 var openBracket1 = _scan('[1, [2]]') as BeginToken; | 745 BeginToken openBracket1 = _scan('[1, [2]]'); |
738 var one = openBracket1.next; | 746 var one = openBracket1.next; |
739 var comma = one.next; | 747 var comma = one.next; |
740 var openBracket2 = comma.next as BeginToken; | 748 BeginToken openBracket2 = comma.next; |
741 var two = openBracket2.next; | 749 var two = openBracket2.next; |
742 var closeBracket1 = two.next; | 750 var closeBracket1 = two.next; |
743 var closeBracket2 = closeBracket1.next; | 751 var closeBracket2 = closeBracket1.next; |
744 expect(closeBracket2.next.type, TokenType.EOF); | 752 expect(closeBracket2.next.type, TokenType.EOF); |
745 expect(openBracket1.endToken, same(closeBracket2)); | 753 expect(openBracket1.endToken, same(closeBracket2)); |
746 expect(openBracket2.endToken, same(closeBracket1)); | 754 expect(openBracket2.endToken, same(closeBracket1)); |
747 } | 755 } |
748 | 756 |
749 void test_matching_parens() { | 757 void test_matching_parens() { |
750 var openParen1 = _scan('(f(x))') as BeginToken; | 758 BeginToken openParen1 = _scan('(f(x))'); |
751 var f = openParen1.next; | 759 var f = openParen1.next; |
752 var openParen2 = f.next as BeginToken; | 760 BeginToken openParen2 = f.next; |
753 var x = openParen2.next; | 761 var x = openParen2.next; |
754 var closeParen1 = x.next; | 762 var closeParen1 = x.next; |
755 var closeParen2 = closeParen1.next; | 763 var closeParen2 = closeParen1.next; |
756 expect(closeParen2.next.type, TokenType.EOF); | 764 expect(closeParen2.next.type, TokenType.EOF); |
757 expect(openParen1.endToken, same(closeParen2)); | 765 expect(openParen1.endToken, same(closeParen2)); |
758 expect(openParen2.endToken, same(closeParen1)); | 766 expect(openParen2.endToken, same(closeParen1)); |
759 } | 767 } |
760 | 768 |
761 void test_minus() { | 769 void test_minus() { |
762 _assertToken(TokenType.MINUS, "-"); | 770 _assertToken(TokenType.MINUS, "-"); |
763 } | 771 } |
764 | 772 |
765 void test_minus_eq() { | 773 void test_minus_eq() { |
766 _assertToken(TokenType.MINUS_EQ, "-="); | 774 _assertToken(TokenType.MINUS_EQ, "-="); |
767 } | 775 } |
768 | 776 |
769 void test_minus_minus() { | 777 void test_minus_minus() { |
770 _assertToken(TokenType.MINUS_MINUS, "--"); | 778 _assertToken(TokenType.MINUS_MINUS, "--"); |
771 } | 779 } |
772 | 780 |
773 void test_mismatched_closer() { | 781 void test_mismatched_closer() { |
774 // When openers and closers are mismatched, analyzer favors considering the | 782 // When openers and closers are mismatched, analyzer favors considering the |
775 // closer to be mismatched, which means that `(])` parses as a pair of | 783 // closer to be mismatched, which means that `(])` parses as a pair of |
776 // matched parentheses with an unmatched closing bracket between them. | 784 // matched parentheses with an unmatched closing bracket between them. |
777 var openParen = _scan('(])') as BeginToken; | 785 ErrorListener listener = new ErrorListener(); |
| 786 BeginToken openParen = scanWithListener('(])', listener); |
778 if (usingFasta) { | 787 if (usingFasta) { |
779 // When openers and closers are mismatched, | 788 // When openers and closers are mismatched, |
780 // fasta favors considering the opener to be mismatched, | 789 // fasta favors considering the opener to be mismatched, |
781 // and inserts synthetic closers as needed. | 790 // and inserts synthetic closers as needed. |
782 // `(])` is parsed as `()])` where the first `)` is synthetic | 791 // `(])` is parsed as `()])` where the first `)` is synthetic |
783 // and the trailing `])` are unmatched. | 792 // and the trailing `])` are unmatched. |
784 var closeParen = openParen.next; | 793 var closeParen = openParen.next; |
785 expect(closeParen.isSynthetic, isTrue); | 794 expect(closeParen.isSynthetic, isTrue); |
786 var closeBracket = closeParen.next; | 795 var closeBracket = closeParen.next; |
787 expect(closeBracket.isSynthetic, isFalse); | 796 expect(closeBracket.isSynthetic, isFalse); |
788 var closeParen2 = closeBracket.next; | 797 var closeParen2 = closeBracket.next; |
789 expect(closeParen2.isSynthetic, isFalse); | 798 expect(closeParen2.isSynthetic, isFalse); |
790 expect(closeParen2.next.type, TokenType.EOF); | 799 expect(closeParen2.next.type, TokenType.EOF); |
791 expect(openParen.endToken, same(closeParen)); | 800 expect(openParen.endToken, same(closeParen)); |
| 801 listener.assertErrors([ |
| 802 new TestError(0, ScannerErrorCode.EXPECTED_TOKEN, [')']), |
| 803 ]); |
792 } else { | 804 } else { |
793 var closeBracket = openParen.next; | 805 var closeBracket = openParen.next; |
794 var closeParen = closeBracket.next; | 806 var closeParen = closeBracket.next; |
795 expect(closeParen.next.type, TokenType.EOF); | 807 expect(closeParen.next.type, TokenType.EOF); |
796 expect(openParen.endToken, same(closeParen)); | 808 expect(openParen.endToken, same(closeParen)); |
| 809 listener.assertNoErrors(); |
797 } | 810 } |
798 } | 811 } |
799 | 812 |
800 void test_mismatched_opener() { | 813 void test_mismatched_opener() { |
801 // When openers and closers are mismatched, analyzer favors considering the | 814 // When openers and closers are mismatched, analyzer favors considering the |
802 // closer to be mismatched, which means that `([)` parses as three unmatched | 815 // closer to be mismatched, which means that `([)` parses as three unmatched |
803 // tokens. | 816 // tokens. |
804 var openParen = _scan('([)') as BeginToken; | 817 ErrorListener listener = new ErrorListener(); |
805 var openBracket = openParen.next as BeginToken; | 818 BeginToken openParen = scanWithListener('([)', listener); |
| 819 BeginToken openBracket = openParen.next; |
806 if (usingFasta) { | 820 if (usingFasta) { |
807 // When openers and closers are mismatched, | 821 // When openers and closers are mismatched, |
808 // fasta favors considering the opener to be mismatched | 822 // fasta favors considering the opener to be mismatched |
809 // and inserts synthetic closers as needed. | 823 // and inserts synthetic closers as needed. |
810 // `([)` is scanned as `([])` where `]` is synthetic. | 824 // `([)` is scanned as `([])` where `]` is synthetic. |
811 var closeBracket = openBracket.next; | 825 var closeBracket = openBracket.next; |
812 expect(closeBracket.isSynthetic, isTrue); | 826 expect(closeBracket.isSynthetic, isTrue); |
813 var closeParen = closeBracket.next; | 827 var closeParen = closeBracket.next; |
814 expect(closeParen.isSynthetic, isFalse); | 828 expect(closeParen.isSynthetic, isFalse); |
815 expect(closeParen.next.type, TokenType.EOF); | 829 expect(closeParen.next.type, TokenType.EOF); |
816 expect(openBracket.endToken, closeBracket); | 830 expect(openBracket.endToken, closeBracket); |
817 expect(openParen.endToken, closeParen); | 831 expect(openParen.endToken, closeParen); |
| 832 listener.assertErrors([ |
| 833 new TestError(1, ScannerErrorCode.EXPECTED_TOKEN, [']']), |
| 834 ]); |
818 } else { | 835 } else { |
819 var closeParen = openBracket.next; | 836 var closeParen = openBracket.next; |
820 expect(closeParen.next.type, TokenType.EOF); | 837 expect(closeParen.next.type, TokenType.EOF); |
821 expect(openParen.endToken, isNull); | 838 expect(openParen.endToken, isNull); |
822 expect(openBracket.endToken, isNull); | 839 expect(openBracket.endToken, isNull); |
| 840 listener.assertNoErrors(); |
823 } | 841 } |
824 } | 842 } |
825 | 843 |
826 void test_mismatched_opener_in_interpolation() { | 844 void test_mismatched_opener_in_interpolation() { |
827 // In an interpolation expression, analyzer considers a closing `}` to | 845 // In an interpolation expression, analyzer considers a closing `}` to |
828 // always match the preceding unmatched `{`, even if there are intervening | 846 // always match the preceding unmatched `{`, even if there are intervening |
829 // unmatched tokens, which means that `"${({(}}"` parses as though the open | 847 // unmatched tokens, which means that `"${({(}}"` parses as though the open |
830 // parens are unmatched but everything else is matched. | 848 // parens are unmatched but everything else is matched. |
831 var stringStart = _scan(r'"${({(}}"'); | 849 var stringStart = _scan(r'"${({(}}"'); |
832 var interpolationStart = stringStart.next as BeginToken; | 850 BeginToken interpolationStart = stringStart.next; |
833 var openParen1 = interpolationStart.next as BeginToken; | 851 BeginToken openParen1 = interpolationStart.next; |
834 var openBrace = openParen1.next as BeginToken; | 852 BeginToken openBrace = openParen1.next; |
835 var openParen2 = openBrace.next as BeginToken; | 853 BeginToken openParen2 = openBrace.next; |
836 var closeBrace = openParen2.next; | 854 var closeBrace = openParen2.next; |
837 var interpolationEnd = closeBrace.next; | 855 var interpolationEnd = closeBrace.next; |
838 var stringEnd = interpolationEnd.next; | 856 var stringEnd = interpolationEnd.next; |
839 expect(stringEnd.next.type, TokenType.EOF); | 857 expect(stringEnd.next.type, TokenType.EOF); |
840 expect(interpolationStart.endToken, same(interpolationEnd)); | 858 expect(interpolationStart.endToken, same(interpolationEnd)); |
841 expect(openParen1.endToken, isNull); | 859 expect(openParen1.endToken, isNull); |
842 expect(openBrace.endToken, same(closeBrace)); | 860 expect(openBrace.endToken, same(closeBrace)); |
843 expect(openParen2.endToken, isNull); | 861 expect(openParen2.endToken, isNull); |
844 } | 862 } |
845 | 863 |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1035 ]); | 1053 ]); |
1036 } | 1054 } |
1037 } | 1055 } |
1038 | 1056 |
1039 void test_string_multi_unterminated_interpolation_block() { | 1057 void test_string_multi_unterminated_interpolation_block() { |
1040 List<Token> expectedTokens = [ | 1058 List<Token> expectedTokens = [ |
1041 new StringToken(TokenType.STRING, "'''", 0), | 1059 new StringToken(TokenType.STRING, "'''", 0), |
1042 new StringToken(TokenType.STRING_INTERPOLATION_EXPRESSION, "\${", 3), | 1060 new StringToken(TokenType.STRING_INTERPOLATION_EXPRESSION, "\${", 3), |
1043 new StringToken(TokenType.IDENTIFIER, "name", 5), | 1061 new StringToken(TokenType.IDENTIFIER, "name", 5), |
1044 ]; | 1062 ]; |
| 1063 var expectedErrors = [ |
| 1064 new TestError(8, ScannerErrorCode.UNTERMINATED_STRING_LITERAL, null), |
| 1065 ]; |
1045 if (usingFasta) { | 1066 if (usingFasta) { |
1046 // fasta inserts synthetic closers | 1067 // fasta inserts synthetic closers |
1047 expectedTokens.addAll([ | 1068 expectedTokens.addAll([ |
1048 new SyntheticToken(TokenType.CLOSE_CURLY_BRACKET, 9), | 1069 new SyntheticToken(TokenType.CLOSE_CURLY_BRACKET, 9), |
1049 new SyntheticStringToken(TokenType.STRING, "'''", 9, 0), | 1070 new SyntheticStringToken(TokenType.STRING, "'''", 9, 0), |
1050 ]); | 1071 ]); |
| 1072 expectedErrors.addAll([ |
| 1073 new TestError(3, ScannerErrorCode.EXPECTED_TOKEN, ['}']), |
| 1074 ]); |
1051 } else { | 1075 } else { |
1052 expectedTokens.addAll([ | 1076 expectedTokens.addAll([ |
1053 new StringToken(TokenType.STRING, "", 9), | 1077 new StringToken(TokenType.STRING, "", 9), |
1054 ]); | 1078 ]); |
1055 } | 1079 } |
1056 _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 8, | 1080 ErrorListener listener = new ErrorListener(); |
1057 "'''\${name", expectedTokens); | 1081 Token token = scanWithListener("'''\${name", listener); |
| 1082 listener.assertErrors(expectedErrors); |
| 1083 _checkTokens(token, expectedTokens); |
1058 } | 1084 } |
1059 | 1085 |
1060 void test_string_multi_unterminated_interpolation_identifier() { | 1086 void test_string_multi_unterminated_interpolation_identifier() { |
1061 List<Token> expectedTokens = [ | 1087 List<Token> expectedTokens = [ |
1062 new StringToken(TokenType.STRING, "'''", 0), | 1088 new StringToken(TokenType.STRING, "'''", 0), |
1063 new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 3), | 1089 new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 3), |
1064 new StringToken(TokenType.IDENTIFIER, "name", 4), | 1090 new StringToken(TokenType.IDENTIFIER, "name", 4), |
1065 ]; | 1091 ]; |
1066 if (usingFasta) { | 1092 if (usingFasta) { |
1067 // fasta inserts synthetic closers | 1093 // fasta inserts synthetic closers |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1213 } | 1239 } |
1214 | 1240 |
1215 void test_string_simple_interpolation_missingIdentifier() { | 1241 void test_string_simple_interpolation_missingIdentifier() { |
1216 var expectedTokens = <Token>[ | 1242 var expectedTokens = <Token>[ |
1217 new StringToken(TokenType.STRING, "'", 0), | 1243 new StringToken(TokenType.STRING, "'", 0), |
1218 new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 1), | 1244 new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 1), |
1219 new StringToken(TokenType.IDENTIFIER, "x", 2), | 1245 new StringToken(TokenType.IDENTIFIER, "x", 2), |
1220 new StringToken(TokenType.STRING, "", 3), | 1246 new StringToken(TokenType.STRING, "", 3), |
1221 new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 3), | 1247 new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 3), |
1222 ]; | 1248 ]; |
| 1249 var expectedErrors = []; |
1223 if (usingFasta) { | 1250 if (usingFasta) { |
1224 // Fasta scanner inserts a synthetic identifier | 1251 // Fasta scanner inserts a synthetic identifier |
1225 expectedTokens.addAll([ | 1252 expectedTokens.addAll([ |
1226 new SyntheticStringToken(TokenType.IDENTIFIER, "", 4, 0), | 1253 new SyntheticStringToken(TokenType.IDENTIFIER, "", 4, 0), |
1227 new StringToken(TokenType.STRING, "'", 4), | 1254 new StringToken(TokenType.STRING, "'", 4), |
1228 ]); | 1255 ]); |
| 1256 expectedErrors.addAll([ |
| 1257 new TestError(4, ScannerErrorCode.MISSING_IDENTIFIER, null), |
| 1258 ]); |
1229 } else { | 1259 } else { |
1230 expectedTokens.addAll([ | 1260 expectedTokens.addAll([ |
1231 new StringToken(TokenType.STRING, "'", 4), | 1261 new StringToken(TokenType.STRING, "'", 4), |
1232 ]); | 1262 ]); |
1233 } | 1263 } |
1234 _assertTokens("'\$x\$'", expectedTokens); | 1264 ErrorListener listener = new ErrorListener(); |
| 1265 Token token = scanWithListener("'\$x\$'", listener); |
| 1266 listener.assertErrors(expectedErrors); |
| 1267 _checkTokens(token, expectedTokens); |
1235 } | 1268 } |
1236 | 1269 |
1237 void test_string_simple_interpolation_nonIdentifier() { | 1270 void test_string_simple_interpolation_nonIdentifier() { |
1238 var expectedTokens = <Token>[ | 1271 var expectedTokens = <Token>[ |
1239 new StringToken(TokenType.STRING, "'", 0), | 1272 new StringToken(TokenType.STRING, "'", 0), |
1240 new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 1), | 1273 new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 1), |
1241 ]; | 1274 ]; |
| 1275 var expectedErrors = []; |
1242 if (usingFasta) { | 1276 if (usingFasta) { |
1243 expectedTokens.addAll([ | 1277 expectedTokens.addAll([ |
1244 new SyntheticStringToken(TokenType.IDENTIFIER, "", 2), | 1278 new SyntheticStringToken(TokenType.IDENTIFIER, "", 2), |
1245 ]); | 1279 ]); |
| 1280 expectedErrors.addAll([ |
| 1281 new TestError(2, ScannerErrorCode.MISSING_IDENTIFIER, null), |
| 1282 ]); |
1246 } | 1283 } |
1247 expectedTokens.addAll([ | 1284 expectedTokens.addAll([ |
1248 new StringToken(TokenType.STRING, "1'", 2), | 1285 new StringToken(TokenType.STRING, "1'", 2), |
1249 ]); | 1286 ]); |
1250 _assertTokens("'\$1'", expectedTokens); | 1287 ErrorListener listener = new ErrorListener(); |
| 1288 Token token = scanWithListener("'\$1'", listener); |
| 1289 listener.assertErrors(expectedErrors); |
| 1290 _checkTokens(token, expectedTokens); |
1251 } | 1291 } |
1252 | 1292 |
1253 void test_string_simple_single() { | 1293 void test_string_simple_single() { |
1254 _assertToken(TokenType.STRING, "'string'"); | 1294 _assertToken(TokenType.STRING, "'string'"); |
1255 } | 1295 } |
1256 | 1296 |
1257 void test_string_simple_unterminated_eof() { | 1297 void test_string_simple_unterminated_eof() { |
1258 String source = "'string"; | 1298 String source = "'string"; |
1259 List<Token> expectedTokens = []; | 1299 List<Token> expectedTokens = []; |
1260 if (usingFasta) { | 1300 if (usingFasta) { |
(...skipping 26 matching lines...) Expand all Loading... |
1287 _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, | 1327 _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, |
1288 usingFasta ? 6 : 7, source, expectedTokens); | 1328 usingFasta ? 6 : 7, source, expectedTokens); |
1289 } | 1329 } |
1290 | 1330 |
1291 void test_string_simple_unterminated_interpolation_block() { | 1331 void test_string_simple_unterminated_interpolation_block() { |
1292 List<Token> expectedTokens = [ | 1332 List<Token> expectedTokens = [ |
1293 new StringToken(TokenType.STRING, "'", 0), | 1333 new StringToken(TokenType.STRING, "'", 0), |
1294 new StringToken(TokenType.STRING_INTERPOLATION_EXPRESSION, "\${", 1), | 1334 new StringToken(TokenType.STRING_INTERPOLATION_EXPRESSION, "\${", 1), |
1295 new StringToken(TokenType.IDENTIFIER, "name", 3), | 1335 new StringToken(TokenType.IDENTIFIER, "name", 3), |
1296 ]; | 1336 ]; |
| 1337 List<TestError> expectedErrors = [ |
| 1338 new TestError(6, ScannerErrorCode.UNTERMINATED_STRING_LITERAL, null), |
| 1339 ]; |
1297 if (usingFasta) { | 1340 if (usingFasta) { |
1298 // fasta inserts synthetic closers | 1341 // fasta inserts synthetic closers |
1299 expectedTokens.addAll([ | 1342 expectedTokens.addAll([ |
1300 new SyntheticToken(TokenType.CLOSE_CURLY_BRACKET, 7), | 1343 new SyntheticToken(TokenType.CLOSE_CURLY_BRACKET, 7), |
1301 new SyntheticStringToken(TokenType.STRING, "'", 7, 0), | 1344 new SyntheticStringToken(TokenType.STRING, "'", 7, 0), |
1302 ]); | 1345 ]); |
| 1346 expectedErrors.addAll([ |
| 1347 new TestError(1, ScannerErrorCode.EXPECTED_TOKEN, ['}']), |
| 1348 ]); |
1303 } else { | 1349 } else { |
1304 expectedTokens.addAll([ | 1350 expectedTokens.addAll([ |
1305 new StringToken(TokenType.STRING, "", 7), | 1351 new StringToken(TokenType.STRING, "", 7), |
1306 ]); | 1352 ]); |
1307 } | 1353 } |
1308 _assertErrorAndTokens(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 6, | 1354 ErrorListener listener = new ErrorListener(); |
1309 "'\${name", expectedTokens); | 1355 Token token = scanWithListener("'\${name", listener); |
| 1356 listener.assertErrors(expectedErrors); |
| 1357 _checkTokens(token, expectedTokens); |
1310 } | 1358 } |
1311 | 1359 |
1312 void test_string_simple_unterminated_interpolation_identifier() { | 1360 void test_string_simple_unterminated_interpolation_identifier() { |
1313 List<Token> expectedTokens = [ | 1361 List<Token> expectedTokens = [ |
1314 new StringToken(TokenType.STRING, "'", 0), | 1362 new StringToken(TokenType.STRING, "'", 0), |
1315 new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 1), | 1363 new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 1), |
1316 new StringToken(TokenType.IDENTIFIER, "name", 2), | 1364 new StringToken(TokenType.IDENTIFIER, "name", 2), |
1317 ]; | 1365 ]; |
1318 if (usingFasta) { | 1366 if (usingFasta) { |
1319 // fasta inserts synthetic closers | 1367 // fasta inserts synthetic closers |
(...skipping 28 matching lines...) Expand all Loading... |
1348 void test_tilde_slash_eq() { | 1396 void test_tilde_slash_eq() { |
1349 _assertToken(TokenType.TILDE_SLASH_EQ, "~/="); | 1397 _assertToken(TokenType.TILDE_SLASH_EQ, "~/="); |
1350 } | 1398 } |
1351 | 1399 |
1352 void test_unclosedPairInInterpolation() { | 1400 void test_unclosedPairInInterpolation() { |
1353 ErrorListener listener = new ErrorListener(); | 1401 ErrorListener listener = new ErrorListener(); |
1354 scanWithListener("'\${(}'", listener); | 1402 scanWithListener("'\${(}'", listener); |
1355 } | 1403 } |
1356 | 1404 |
1357 void test_unmatched_openers() { | 1405 void test_unmatched_openers() { |
1358 var openBrace = _scan('{[(') as BeginToken; | 1406 BeginToken openBrace = _scan('{[('); |
1359 var openBracket = openBrace.next as BeginToken; | 1407 BeginToken openBracket = openBrace.next; |
1360 var openParen = openBracket.next as BeginToken; | 1408 BeginToken openParen = openBracket.next; |
1361 expect(openParen.next.type, TokenType.EOF); | 1409 expect(openParen.next.type, TokenType.EOF); |
1362 expect(openBrace.endToken, isNull); | 1410 expect(openBrace.endToken, isNull); |
1363 expect(openBracket.endToken, isNull); | 1411 expect(openBracket.endToken, isNull); |
1364 expect(openParen.endToken, isNull); | 1412 expect(openParen.endToken, isNull); |
1365 } | 1413 } |
1366 | 1414 |
1367 void _assertComment(TokenType commentType, String source, | 1415 void _assertComment(TokenType commentType, String source, |
1368 {bool genericMethodComments: false}) { | 1416 {bool genericMethodComments: false}) { |
1369 // | 1417 // |
1370 // Test without a trailing end-of-line marker | 1418 // Test without a trailing end-of-line marker |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1451 expect((value as Keyword).lexeme, source); | 1499 expect((value as Keyword).lexeme, source); |
1452 expect(token.next.type, TokenType.EOF); | 1500 expect(token.next.type, TokenType.EOF); |
1453 } | 1501 } |
1454 | 1502 |
1455 /** | 1503 /** |
1456 * Assert that the token scanned from the given [source] has the | 1504 * Assert that the token scanned from the given [source] has the |
1457 * [expectedType]. | 1505 * [expectedType]. |
1458 */ | 1506 */ |
1459 Token _assertToken(TokenType expectedType, String source, | 1507 Token _assertToken(TokenType expectedType, String source, |
1460 {bool lazyAssignmentOperators: false}) { | 1508 {bool lazyAssignmentOperators: false}) { |
1461 Token originalToken = | 1509 // Fasta generates errors for unmatched '{', '[', etc |
1462 _scan(source, lazyAssignmentOperators: lazyAssignmentOperators); | 1510 Token originalToken = _scan(source, |
| 1511 lazyAssignmentOperators: lazyAssignmentOperators, |
| 1512 ignoreErrors: usingFasta); |
1463 expect(originalToken, isNotNull); | 1513 expect(originalToken, isNotNull); |
1464 expect(originalToken.type, expectedType); | 1514 expect(originalToken.type, expectedType); |
1465 expect(originalToken.offset, 0); | 1515 expect(originalToken.offset, 0); |
1466 expect(originalToken.length, source.length); | 1516 expect(originalToken.length, source.length); |
1467 expect(originalToken.lexeme, source); | 1517 expect(originalToken.lexeme, source); |
1468 if (expectedType == TokenType.SCRIPT_TAG) { | 1518 if (expectedType == TokenType.SCRIPT_TAG) { |
1469 // Adding space before the script tag is not allowed, and adding text at | 1519 // Adding space before the script tag is not allowed, and adding text at |
1470 // the end changes nothing. | 1520 // the end changes nothing. |
1471 return originalToken; | 1521 return originalToken; |
1472 } else if (expectedType == TokenType.SINGLE_LINE_COMMENT) { | 1522 } else if (expectedType == TokenType.SINGLE_LINE_COMMENT) { |
1473 // Adding space to an end-of-line comment changes the comment. | 1523 // Adding space to an end-of-line comment changes the comment. |
1474 Token tokenWithSpaces = | 1524 Token tokenWithSpaces = _scan(" $source", |
1475 _scan(" $source", lazyAssignmentOperators: lazyAssignmentOperators); | 1525 lazyAssignmentOperators: lazyAssignmentOperators, |
| 1526 ignoreErrors: usingFasta); |
1476 expect(tokenWithSpaces, isNotNull); | 1527 expect(tokenWithSpaces, isNotNull); |
1477 expect(tokenWithSpaces.type, expectedType); | 1528 expect(tokenWithSpaces.type, expectedType); |
1478 expect(tokenWithSpaces.offset, 1); | 1529 expect(tokenWithSpaces.offset, 1); |
1479 expect(tokenWithSpaces.length, source.length); | 1530 expect(tokenWithSpaces.length, source.length); |
1480 expect(tokenWithSpaces.lexeme, source); | 1531 expect(tokenWithSpaces.lexeme, source); |
1481 return originalToken; | 1532 return originalToken; |
1482 } else if (expectedType == TokenType.INT || | 1533 } else if (expectedType == TokenType.INT || |
1483 expectedType == TokenType.DOUBLE) { | 1534 expectedType == TokenType.DOUBLE) { |
1484 Token tokenWithLowerD = | 1535 Token tokenWithLowerD = _scan("${source}d", |
1485 _scan("${source}d", lazyAssignmentOperators: lazyAssignmentOperators); | 1536 lazyAssignmentOperators: lazyAssignmentOperators, |
| 1537 ignoreErrors: usingFasta); |
1486 expect(tokenWithLowerD, isNotNull); | 1538 expect(tokenWithLowerD, isNotNull); |
1487 expect(tokenWithLowerD.type, expectedType); | 1539 expect(tokenWithLowerD.type, expectedType); |
1488 expect(tokenWithLowerD.offset, 0); | 1540 expect(tokenWithLowerD.offset, 0); |
1489 expect(tokenWithLowerD.length, source.length); | 1541 expect(tokenWithLowerD.length, source.length); |
1490 expect(tokenWithLowerD.lexeme, source); | 1542 expect(tokenWithLowerD.lexeme, source); |
1491 Token tokenWithUpperD = | 1543 Token tokenWithUpperD = _scan("${source}D", |
1492 _scan("${source}D", lazyAssignmentOperators: lazyAssignmentOperators); | 1544 lazyAssignmentOperators: lazyAssignmentOperators, |
| 1545 ignoreErrors: usingFasta); |
1493 expect(tokenWithUpperD, isNotNull); | 1546 expect(tokenWithUpperD, isNotNull); |
1494 expect(tokenWithUpperD.type, expectedType); | 1547 expect(tokenWithUpperD.type, expectedType); |
1495 expect(tokenWithUpperD.offset, 0); | 1548 expect(tokenWithUpperD.offset, 0); |
1496 expect(tokenWithUpperD.length, source.length); | 1549 expect(tokenWithUpperD.length, source.length); |
1497 expect(tokenWithUpperD.lexeme, source); | 1550 expect(tokenWithUpperD.lexeme, source); |
1498 } | 1551 } |
1499 Token tokenWithSpaces = | 1552 Token tokenWithSpaces = _scan(" $source ", |
1500 _scan(" $source ", lazyAssignmentOperators: lazyAssignmentOperators); | 1553 lazyAssignmentOperators: lazyAssignmentOperators, |
| 1554 ignoreErrors: usingFasta); |
1501 expect(tokenWithSpaces, isNotNull); | 1555 expect(tokenWithSpaces, isNotNull); |
1502 expect(tokenWithSpaces.type, expectedType); | 1556 expect(tokenWithSpaces.type, expectedType); |
1503 expect(tokenWithSpaces.offset, 1); | 1557 expect(tokenWithSpaces.offset, 1); |
1504 expect(tokenWithSpaces.length, source.length); | 1558 expect(tokenWithSpaces.length, source.length); |
1505 expect(tokenWithSpaces.lexeme, source); | 1559 expect(tokenWithSpaces.lexeme, source); |
1506 | 1560 |
1507 // Fasta inserts missing closers (']', '}', ')') | 1561 // Fasta inserts missing closers (']', '}', ')') |
1508 //expect(originalToken.next.type, TokenType.EOF); | 1562 //expect(originalToken.next.type, TokenType.EOF); |
1509 return originalToken; | 1563 return originalToken; |
1510 } | 1564 } |
(...skipping 20 matching lines...) Expand all Loading... |
1531 expect(token.lexeme, expectedToken.lexeme, | 1585 expect(token.lexeme, expectedToken.lexeme, |
1532 reason: "Wrong lexeme for token $i"); | 1586 reason: "Wrong lexeme for token $i"); |
1533 token = token.next; | 1587 token = token.next; |
1534 expect(token, isNotNull); | 1588 expect(token, isNotNull); |
1535 } | 1589 } |
1536 expect(token.type, TokenType.EOF); | 1590 expect(token.type, TokenType.EOF); |
1537 } | 1591 } |
1538 | 1592 |
1539 Token _scan(String source, | 1593 Token _scan(String source, |
1540 {bool genericMethodComments: false, | 1594 {bool genericMethodComments: false, |
1541 bool lazyAssignmentOperators: false}) { | 1595 bool lazyAssignmentOperators: false, |
| 1596 bool ignoreErrors: false}) { |
1542 ErrorListener listener = new ErrorListener(); | 1597 ErrorListener listener = new ErrorListener(); |
1543 Token token = scanWithListener(source, listener, | 1598 Token token = scanWithListener(source, listener, |
1544 genericMethodComments: genericMethodComments, | 1599 genericMethodComments: genericMethodComments, |
1545 lazyAssignmentOperators: lazyAssignmentOperators); | 1600 lazyAssignmentOperators: lazyAssignmentOperators); |
1546 listener.assertNoErrors(); | 1601 if (!ignoreErrors) { |
| 1602 listener.assertNoErrors(); |
| 1603 } |
1547 return token; | 1604 return token; |
1548 } | 1605 } |
1549 } | 1606 } |
1550 | 1607 |
1551 class TestError { | 1608 class TestError { |
1552 final int offset; | 1609 final int offset; |
1553 final ErrorCode errorCode; | 1610 final ErrorCode errorCode; |
1554 final List<Object> arguments; | 1611 final List<Object> arguments; |
1555 | 1612 |
1556 TestError(this.offset, this.errorCode, this.arguments); | 1613 TestError(this.offset, this.errorCode, this.arguments); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1662 _TestScanner(CharacterReader reader, [this.listener]) : super.create(reader); | 1719 _TestScanner(CharacterReader reader, [this.listener]) : super.create(reader); |
1663 | 1720 |
1664 @override | 1721 @override |
1665 void reportError( | 1722 void reportError( |
1666 ScannerErrorCode errorCode, int offset, List<Object> arguments) { | 1723 ScannerErrorCode errorCode, int offset, List<Object> arguments) { |
1667 if (listener != null) { | 1724 if (listener != null) { |
1668 listener.errors.add(new TestError(offset, errorCode, arguments)); | 1725 listener.errors.add(new TestError(offset, errorCode, arguments)); |
1669 } | 1726 } |
1670 } | 1727 } |
1671 } | 1728 } |
OLD | NEW |