microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.1.3

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

compiler/qsc_parse/src/lex/cooked/tests.rs

1830lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use super::{Lexer, Token, TokenKind};
5use crate::lex::Delim;
6use expect_test::{expect, Expect};
7use qsc_data_structures::span::Span;
8
9fn check(input: &str, expect: &Expect) {
10 let actual: Vec<_> = Lexer::new(input).collect();
11 expect.assert_debug_eq(&actual);
12}
13
14fn op_string(kind: TokenKind) -> Option<String> {
15 match kind {
16 TokenKind::AposIdent => Some("'T".to_string()),
17 TokenKind::At => Some("@".to_string()),
18 TokenKind::Bang => Some("!".to_string()),
19 TokenKind::Bar => Some("|".to_string()),
20 TokenKind::BinOpEq(op) => Some(format!("{op}=")),
21 TokenKind::Close(Delim::Brace) => Some("}".to_string()),
22 TokenKind::Close(Delim::Bracket) => Some("]".to_string()),
23 TokenKind::Close(Delim::Paren) => Some(")".to_string()),
24 TokenKind::ClosedBinOp(op) => Some(op.to_string()),
25 TokenKind::Colon => Some(":".to_string()),
26 TokenKind::ColonColon => Some("::".to_string()),
27 TokenKind::Comma => Some(",".to_string()),
28 TokenKind::Dot => Some(".".to_string()),
29 TokenKind::DotDot => Some("..".to_string()),
30 TokenKind::DotDotDot => Some("...".to_string()),
31 TokenKind::Eq => Some("=".to_string()),
32 TokenKind::EqEq => Some("==".to_string()),
33 TokenKind::FatArrow => Some("=>".to_string()),
34 TokenKind::Gt => Some(">".to_string()),
35 TokenKind::Gte => Some(">=".to_string()),
36 TokenKind::LArrow => Some("<-".to_string()),
37 TokenKind::Lt => Some("<".to_string()),
38 TokenKind::Lte => Some("<=".to_string()),
39 TokenKind::Ne => Some("!=".to_string()),
40 TokenKind::Open(Delim::Brace) => Some("{".to_string()),
41 TokenKind::Open(Delim::Bracket) => Some("[".to_string()),
42 TokenKind::Open(Delim::Paren) => Some("(".to_string()),
43 TokenKind::Question => Some("?".to_string()),
44 TokenKind::RArrow => Some("->".to_string()),
45 TokenKind::Semi => Some(";".to_string()),
46 TokenKind::TildeTildeTilde => Some("~~~".to_string()),
47 TokenKind::WSlash => Some("w/".to_string()),
48 TokenKind::WSlashEq => Some("w/=".to_string()),
49 TokenKind::BigInt(_)
50 | TokenKind::DocComment
51 | TokenKind::Eof
52 | TokenKind::Float
53 | TokenKind::Ident
54 | TokenKind::Int(_)
55 | TokenKind::Keyword(_)
56 | TokenKind::String(_) => None,
57 }
58}
59
60#[test]
61fn basic_ops() {
62 for kind in enum_iterator::all() {
63 let Some(input) = op_string(kind) else {
64 continue;
65 };
66 let actual: Vec<_> = Lexer::new(&input).collect();
67 let len = input
68 .len()
69 .try_into()
70 .expect("input length should fit into u32");
71 assert_eq!(
72 actual,
73 vec![Ok(Token {
74 kind,
75 span: Span { lo: 0, hi: len }
76 }),]
77 );
78 }
79}
80
81#[test]
82fn empty() {
83 check(
84 "",
85 &expect![[r#"
86 []
87 "#]],
88 );
89}
90
91#[test]
92fn amp() {
93 check(
94 "&",
95 &expect![[r#"
96 [
97 Err(
98 IncompleteEof(
99 Single(
100 Amp,
101 ),
102 ClosedBinOp(
103 AmpAmpAmp,
104 ),
105 Span {
106 lo: 1,
107 hi: 1,
108 },
109 ),
110 ),
111 ]
112 "#]],
113 );
114}
115
116#[test]
117fn amp_amp() {
118 check(
119 "&&",
120 &expect![[r#"
121 [
122 Err(
123 IncompleteEof(
124 Single(
125 Amp,
126 ),
127 ClosedBinOp(
128 AmpAmpAmp,
129 ),
130 Span {
131 lo: 2,
132 hi: 2,
133 },
134 ),
135 ),
136 ]
137 "#]],
138 );
139}
140
141#[test]
142fn amp_plus() {
143 check(
144 "&+",
145 &expect![[r#"
146 [
147 Err(
148 Incomplete(
149 Single(
150 Amp,
151 ),
152 ClosedBinOp(
153 AmpAmpAmp,
154 ),
155 Single(
156 Plus,
157 ),
158 Span {
159 lo: 1,
160 hi: 2,
161 },
162 ),
163 ),
164 Ok(
165 Token {
166 kind: ClosedBinOp(
167 Plus,
168 ),
169 span: Span {
170 lo: 1,
171 hi: 2,
172 },
173 },
174 ),
175 ]
176 "#]],
177 );
178}
179
180#[test]
181fn amp_multibyte() {
182 check(
183 "&🦀",
184 &expect![[r#"
185 [
186 Err(
187 Incomplete(
188 Single(
189 Amp,
190 ),
191 ClosedBinOp(
192 AmpAmpAmp,
193 ),
194 Unknown,
195 Span {
196 lo: 1,
197 hi: 5,
198 },
199 ),
200 ),
201 Err(
202 Unknown(
203 '🦀',
204 Span {
205 lo: 1,
206 hi: 5,
207 },
208 ),
209 ),
210 ]
211 "#]],
212 );
213}
214
215#[test]
216fn amp_amp_amp_amp_amp_amp() {
217 check(
218 "&&&&&&",
219 &expect![[r#"
220 [
221 Ok(
222 Token {
223 kind: ClosedBinOp(
224 AmpAmpAmp,
225 ),
226 span: Span {
227 lo: 0,
228 hi: 3,
229 },
230 },
231 ),
232 Ok(
233 Token {
234 kind: ClosedBinOp(
235 AmpAmpAmp,
236 ),
237 span: Span {
238 lo: 3,
239 hi: 6,
240 },
241 },
242 ),
243 ]
244 "#]],
245 );
246}
247
248#[test]
249fn caret_caret() {
250 check(
251 "^^",
252 &expect![[r#"
253 [
254 Err(
255 IncompleteEof(
256 Single(
257 Caret,
258 ),
259 ClosedBinOp(
260 CaretCaretCaret,
261 ),
262 Span {
263 lo: 2,
264 hi: 2,
265 },
266 ),
267 ),
268 ]
269 "#]],
270 );
271}
272
273#[test]
274fn and_ws_eq() {
275 check(
276 "and =",
277 &expect![[r#"
278 [
279 Ok(
280 Token {
281 kind: ClosedBinOp(
282 And,
283 ),
284 span: Span {
285 lo: 0,
286 hi: 3,
287 },
288 },
289 ),
290 Ok(
291 Token {
292 kind: Eq,
293 span: Span {
294 lo: 4,
295 hi: 5,
296 },
297 },
298 ),
299 ]
300 "#]],
301 );
302}
303
304#[test]
305fn w() {
306 check(
307 "w",
308 &expect![[r#"
309 [
310 Ok(
311 Token {
312 kind: Ident,
313 span: Span {
314 lo: 0,
315 hi: 1,
316 },
317 },
318 ),
319 ]
320 "#]],
321 );
322}
323
324#[test]
325fn w_slash_eq_ident() {
326 check(
327 "w/=foo",
328 &expect![[r#"
329 [
330 Ok(
331 Token {
332 kind: WSlashEq,
333 span: Span {
334 lo: 0,
335 hi: 3,
336 },
337 },
338 ),
339 Ok(
340 Token {
341 kind: Ident,
342 span: Span {
343 lo: 3,
344 hi: 6,
345 },
346 },
347 ),
348 ]
349 "#]],
350 );
351}
352
353#[test]
354fn int() {
355 check(
356 "123",
357 &expect![[r#"
358 [
359 Ok(
360 Token {
361 kind: Int(
362 Decimal,
363 ),
364 span: Span {
365 lo: 0,
366 hi: 3,
367 },
368 },
369 ),
370 ]
371 "#]],
372 );
373}
374
375#[test]
376fn negative_int() {
377 check(
378 "-123",
379 &expect![[r#"
380 [
381 Ok(
382 Token {
383 kind: ClosedBinOp(
384 Minus,
385 ),
386 span: Span {
387 lo: 0,
388 hi: 1,
389 },
390 },
391 ),
392 Ok(
393 Token {
394 kind: Int(
395 Decimal,
396 ),
397 span: Span {
398 lo: 1,
399 hi: 4,
400 },
401 },
402 ),
403 ]
404 "#]],
405 );
406}
407
408#[test]
409fn positive_int() {
410 check(
411 "+123",
412 &expect![[r#"
413 [
414 Ok(
415 Token {
416 kind: ClosedBinOp(
417 Plus,
418 ),
419 span: Span {
420 lo: 0,
421 hi: 1,
422 },
423 },
424 ),
425 Ok(
426 Token {
427 kind: Int(
428 Decimal,
429 ),
430 span: Span {
431 lo: 1,
432 hi: 4,
433 },
434 },
435 ),
436 ]
437 "#]],
438 );
439}
440
441#[test]
442fn bigint() {
443 check(
444 "123L",
445 &expect![[r#"
446 [
447 Ok(
448 Token {
449 kind: BigInt(
450 Decimal,
451 ),
452 span: Span {
453 lo: 0,
454 hi: 4,
455 },
456 },
457 ),
458 ]
459 "#]],
460 );
461}
462
463#[test]
464fn negative_bigint() {
465 check(
466 "-123L",
467 &expect![[r#"
468 [
469 Ok(
470 Token {
471 kind: ClosedBinOp(
472 Minus,
473 ),
474 span: Span {
475 lo: 0,
476 hi: 1,
477 },
478 },
479 ),
480 Ok(
481 Token {
482 kind: BigInt(
483 Decimal,
484 ),
485 span: Span {
486 lo: 1,
487 hi: 5,
488 },
489 },
490 ),
491 ]
492 "#]],
493 );
494}
495
496#[test]
497fn positive_bigint() {
498 check(
499 "+123L",
500 &expect![[r#"
501 [
502 Ok(
503 Token {
504 kind: ClosedBinOp(
505 Plus,
506 ),
507 span: Span {
508 lo: 0,
509 hi: 1,
510 },
511 },
512 ),
513 Ok(
514 Token {
515 kind: BigInt(
516 Decimal,
517 ),
518 span: Span {
519 lo: 1,
520 hi: 5,
521 },
522 },
523 ),
524 ]
525 "#]],
526 );
527}
528
529#[test]
530fn float() {
531 check(
532 "1.23",
533 &expect![[r#"
534 [
535 Ok(
536 Token {
537 kind: Float,
538 span: Span {
539 lo: 0,
540 hi: 4,
541 },
542 },
543 ),
544 ]
545 "#]],
546 );
547}
548
549#[test]
550fn negative_float() {
551 check(
552 "-1.23",
553 &expect![[r#"
554 [
555 Ok(
556 Token {
557 kind: ClosedBinOp(
558 Minus,
559 ),
560 span: Span {
561 lo: 0,
562 hi: 1,
563 },
564 },
565 ),
566 Ok(
567 Token {
568 kind: Float,
569 span: Span {
570 lo: 1,
571 hi: 5,
572 },
573 },
574 ),
575 ]
576 "#]],
577 );
578}
579
580#[test]
581fn positive_float() {
582 check(
583 "+1.23",
584 &expect![[r#"
585 [
586 Ok(
587 Token {
588 kind: ClosedBinOp(
589 Plus,
590 ),
591 span: Span {
592 lo: 0,
593 hi: 1,
594 },
595 },
596 ),
597 Ok(
598 Token {
599 kind: Float,
600 span: Span {
601 lo: 1,
602 hi: 5,
603 },
604 },
605 ),
606 ]
607 "#]],
608 );
609}
610
611#[test]
612fn leading_point() {
613 check(
614 ".1",
615 &expect![[r#"
616 [
617 Ok(
618 Token {
619 kind: Dot,
620 span: Span {
621 lo: 0,
622 hi: 1,
623 },
624 },
625 ),
626 Ok(
627 Token {
628 kind: Int(
629 Decimal,
630 ),
631 span: Span {
632 lo: 1,
633 hi: 2,
634 },
635 },
636 ),
637 ]
638 "#]],
639 );
640}
641
642#[test]
643fn trailing_point() {
644 check(
645 "1.",
646 &expect![[r#"
647 [
648 Ok(
649 Token {
650 kind: Float,
651 span: Span {
652 lo: 0,
653 hi: 2,
654 },
655 },
656 ),
657 ]
658 "#]],
659 );
660}
661
662#[test]
663fn leading_zero_float() {
664 check(
665 "0.42",
666 &expect![[r#"
667 [
668 Ok(
669 Token {
670 kind: Float,
671 span: Span {
672 lo: 0,
673 hi: 4,
674 },
675 },
676 ),
677 ]
678 "#]],
679 );
680}
681
682#[test]
683fn dot_dot_int() {
684 check(
685 "..1",
686 &expect![[r#"
687 [
688 Ok(
689 Token {
690 kind: DotDot,
691 span: Span {
692 lo: 0,
693 hi: 2,
694 },
695 },
696 ),
697 Ok(
698 Token {
699 kind: Int(
700 Decimal,
701 ),
702 span: Span {
703 lo: 2,
704 hi: 3,
705 },
706 },
707 ),
708 ]
709 "#]],
710 );
711}
712
713#[test]
714fn dot_dot_dot_int() {
715 check(
716 "...1",
717 &expect![[r#"
718 [
719 Ok(
720 Token {
721 kind: DotDotDot,
722 span: Span {
723 lo: 0,
724 hi: 3,
725 },
726 },
727 ),
728 Ok(
729 Token {
730 kind: Int(
731 Decimal,
732 ),
733 span: Span {
734 lo: 3,
735 hi: 4,
736 },
737 },
738 ),
739 ]
740 "#]],
741 );
742}
743
744#[test]
745fn int_dot_dot() {
746 check(
747 "1..",
748 &expect![[r#"
749 [
750 Ok(
751 Token {
752 kind: Int(
753 Decimal,
754 ),
755 span: Span {
756 lo: 0,
757 hi: 1,
758 },
759 },
760 ),
761 Ok(
762 Token {
763 kind: DotDot,
764 span: Span {
765 lo: 1,
766 hi: 3,
767 },
768 },
769 ),
770 ]
771 "#]],
772 );
773}
774
775#[test]
776fn int_dot_dot_dot() {
777 check(
778 "1...",
779 &expect![[r#"
780 [
781 Ok(
782 Token {
783 kind: Int(
784 Decimal,
785 ),
786 span: Span {
787 lo: 0,
788 hi: 1,
789 },
790 },
791 ),
792 Ok(
793 Token {
794 kind: DotDotDot,
795 span: Span {
796 lo: 1,
797 hi: 4,
798 },
799 },
800 ),
801 ]
802 "#]],
803 );
804}
805
806#[test]
807fn dot_dot_dot_int_dot_dot_dot() {
808 check(
809 "...1...",
810 &expect![[r#"
811 [
812 Ok(
813 Token {
814 kind: DotDotDot,
815 span: Span {
816 lo: 0,
817 hi: 3,
818 },
819 },
820 ),
821 Ok(
822 Token {
823 kind: Int(
824 Decimal,
825 ),
826 span: Span {
827 lo: 3,
828 hi: 4,
829 },
830 },
831 ),
832 Ok(
833 Token {
834 kind: DotDotDot,
835 span: Span {
836 lo: 4,
837 hi: 7,
838 },
839 },
840 ),
841 ]
842 "#]],
843 );
844}
845
846#[test]
847fn two_points_with_leading() {
848 check(
849 ".1.2",
850 &expect![[r#"
851 [
852 Ok(
853 Token {
854 kind: Dot,
855 span: Span {
856 lo: 0,
857 hi: 1,
858 },
859 },
860 ),
861 Ok(
862 Token {
863 kind: Float,
864 span: Span {
865 lo: 1,
866 hi: 4,
867 },
868 },
869 ),
870 ]
871 "#]],
872 );
873}
874
875#[test]
876fn leading_point_exp() {
877 check(
878 ".1e2",
879 &expect![[r#"
880 [
881 Ok(
882 Token {
883 kind: Dot,
884 span: Span {
885 lo: 0,
886 hi: 1,
887 },
888 },
889 ),
890 Ok(
891 Token {
892 kind: Float,
893 span: Span {
894 lo: 1,
895 hi: 4,
896 },
897 },
898 ),
899 ]
900 "#]],
901 );
902}
903
904#[test]
905fn ident() {
906 check(
907 "foo",
908 &expect![[r#"
909 [
910 Ok(
911 Token {
912 kind: Ident,
913 span: Span {
914 lo: 0,
915 hi: 3,
916 },
917 },
918 ),
919 ]
920 "#]],
921 );
922}
923
924#[test]
925fn string() {
926 check(
927 r#""string""#,
928 &expect![[r#"
929 [
930 Ok(
931 Token {
932 kind: String(
933 Normal,
934 ),
935 span: Span {
936 lo: 0,
937 hi: 8,
938 },
939 },
940 ),
941 ]
942 "#]],
943 );
944}
945
946#[test]
947fn string_empty() {
948 check(
949 r#""""#,
950 &expect![[r#"
951 [
952 Ok(
953 Token {
954 kind: String(
955 Normal,
956 ),
957 span: Span {
958 lo: 0,
959 hi: 2,
960 },
961 },
962 ),
963 ]
964 "#]],
965 );
966}
967
968#[test]
969fn string_missing_ending() {
970 check(
971 r#""Uh oh..."#,
972 &expect![[r#"
973 [
974 Err(
975 UnterminatedString(
976 Span {
977 lo: 0,
978 hi: 0,
979 },
980 ),
981 ),
982 ]
983 "#]],
984 );
985}
986
987#[test]
988fn interpolated_string_missing_ending() {
989 check(
990 r#"$"string"#,
991 &expect![[r#"
992 [
993 Err(
994 UnterminatedString(
995 Span {
996 lo: 0,
997 hi: 0,
998 },
999 ),
1000 ),
1001 ]
1002 "#]],
1003 );
1004}
1005
1006#[test]
1007fn interpolated_string() {
1008 check(
1009 r#"$"string""#,
1010 &expect![[r#"
1011 [
1012 Ok(
1013 Token {
1014 kind: String(
1015 Interpolated(
1016 DollarQuote,
1017 Quote,
1018 ),
1019 ),
1020 span: Span {
1021 lo: 0,
1022 hi: 9,
1023 },
1024 },
1025 ),
1026 ]
1027 "#]],
1028 );
1029}
1030
1031#[test]
1032fn interpolated_string_braced() {
1033 check(
1034 r#"$"{x}""#,
1035 &expect![[r#"
1036 [
1037 Ok(
1038 Token {
1039 kind: String(
1040 Interpolated(
1041 DollarQuote,
1042 LBrace,
1043 ),
1044 ),
1045 span: Span {
1046 lo: 0,
1047 hi: 3,
1048 },
1049 },
1050 ),
1051 Ok(
1052 Token {
1053 kind: Ident,
1054 span: Span {
1055 lo: 3,
1056 hi: 4,
1057 },
1058 },
1059 ),
1060 Ok(
1061 Token {
1062 kind: String(
1063 Interpolated(
1064 RBrace,
1065 Quote,
1066 ),
1067 ),
1068 span: Span {
1069 lo: 4,
1070 hi: 6,
1071 },
1072 },
1073 ),
1074 ]
1075 "#]],
1076 );
1077}
1078
1079#[test]
1080fn interpolated_string_escape_brace() {
1081 check(
1082 r#"$"\{""#,
1083 &expect![[r#"
1084 [
1085 Ok(
1086 Token {
1087 kind: String(
1088 Interpolated(
1089 DollarQuote,
1090 Quote,
1091 ),
1092 ),
1093 span: Span {
1094 lo: 0,
1095 hi: 5,
1096 },
1097 },
1098 ),
1099 ]
1100 "#]],
1101 );
1102}
1103
1104#[test]
1105fn interpolated_string_unclosed_brace() {
1106 check(
1107 r#"$"{"#,
1108 &expect![[r#"
1109 [
1110 Ok(
1111 Token {
1112 kind: String(
1113 Interpolated(
1114 DollarQuote,
1115 LBrace,
1116 ),
1117 ),
1118 span: Span {
1119 lo: 0,
1120 hi: 3,
1121 },
1122 },
1123 ),
1124 ]
1125 "#]],
1126 );
1127}
1128
1129#[test]
1130fn interpolated_string_unclosed_brace_quote() {
1131 check(
1132 r#"$"{""#,
1133 &expect![[r#"
1134 [
1135 Ok(
1136 Token {
1137 kind: String(
1138 Interpolated(
1139 DollarQuote,
1140 LBrace,
1141 ),
1142 ),
1143 span: Span {
1144 lo: 0,
1145 hi: 3,
1146 },
1147 },
1148 ),
1149 Err(
1150 UnterminatedString(
1151 Span {
1152 lo: 3,
1153 hi: 3,
1154 },
1155 ),
1156 ),
1157 ]
1158 "#]],
1159 );
1160}
1161
1162#[test]
1163fn interpolated_string_unopened_brace() {
1164 check(
1165 r#"$"}"#,
1166 &expect![[r#"
1167 [
1168 Err(
1169 UnterminatedString(
1170 Span {
1171 lo: 0,
1172 hi: 0,
1173 },
1174 ),
1175 ),
1176 ]
1177 "#]],
1178 );
1179}
1180
1181#[test]
1182fn interpolated_string_unopened_brace_quote() {
1183 check(
1184 r#"$"}""#,
1185 &expect![[r#"
1186 [
1187 Ok(
1188 Token {
1189 kind: String(
1190 Interpolated(
1191 DollarQuote,
1192 Quote,
1193 ),
1194 ),
1195 span: Span {
1196 lo: 0,
1197 hi: 4,
1198 },
1199 },
1200 ),
1201 ]
1202 "#]],
1203 );
1204}
1205
1206#[test]
1207fn interpolated_string_braced_index() {
1208 check(
1209 r#"$"{xs[0]}""#,
1210 &expect![[r#"
1211 [
1212 Ok(
1213 Token {
1214 kind: String(
1215 Interpolated(
1216 DollarQuote,
1217 LBrace,
1218 ),
1219 ),
1220 span: Span {
1221 lo: 0,
1222 hi: 3,
1223 },
1224 },
1225 ),
1226 Ok(
1227 Token {
1228 kind: Ident,
1229 span: Span {
1230 lo: 3,
1231 hi: 5,
1232 },
1233 },
1234 ),
1235 Ok(
1236 Token {
1237 kind: Open(
1238 Bracket,
1239 ),
1240 span: Span {
1241 lo: 5,
1242 hi: 6,
1243 },
1244 },
1245 ),
1246 Ok(
1247 Token {
1248 kind: Int(
1249 Decimal,
1250 ),
1251 span: Span {
1252 lo: 6,
1253 hi: 7,
1254 },
1255 },
1256 ),
1257 Ok(
1258 Token {
1259 kind: Close(
1260 Bracket,
1261 ),
1262 span: Span {
1263 lo: 7,
1264 hi: 8,
1265 },
1266 },
1267 ),
1268 Ok(
1269 Token {
1270 kind: String(
1271 Interpolated(
1272 RBrace,
1273 Quote,
1274 ),
1275 ),
1276 span: Span {
1277 lo: 8,
1278 hi: 10,
1279 },
1280 },
1281 ),
1282 ]
1283 "#]],
1284 );
1285}
1286
1287#[test]
1288fn interpolated_string_two_braced() {
1289 check(
1290 r#"$"{x} {y}""#,
1291 &expect![[r#"
1292 [
1293 Ok(
1294 Token {
1295 kind: String(
1296 Interpolated(
1297 DollarQuote,
1298 LBrace,
1299 ),
1300 ),
1301 span: Span {
1302 lo: 0,
1303 hi: 3,
1304 },
1305 },
1306 ),
1307 Ok(
1308 Token {
1309 kind: Ident,
1310 span: Span {
1311 lo: 3,
1312 hi: 4,
1313 },
1314 },
1315 ),
1316 Ok(
1317 Token {
1318 kind: String(
1319 Interpolated(
1320 RBrace,
1321 LBrace,
1322 ),
1323 ),
1324 span: Span {
1325 lo: 4,
1326 hi: 7,
1327 },
1328 },
1329 ),
1330 Ok(
1331 Token {
1332 kind: Ident,
1333 span: Span {
1334 lo: 7,
1335 hi: 8,
1336 },
1337 },
1338 ),
1339 Ok(
1340 Token {
1341 kind: String(
1342 Interpolated(
1343 RBrace,
1344 Quote,
1345 ),
1346 ),
1347 span: Span {
1348 lo: 8,
1349 hi: 10,
1350 },
1351 },
1352 ),
1353 ]
1354 "#]],
1355 );
1356}
1357
1358#[test]
1359fn interpolated_string_braced_normal_string() {
1360 check(
1361 r#"$"{"{}"}""#,
1362 &expect![[r#"
1363 [
1364 Ok(
1365 Token {
1366 kind: String(
1367 Interpolated(
1368 DollarQuote,
1369 LBrace,
1370 ),
1371 ),
1372 span: Span {
1373 lo: 0,
1374 hi: 3,
1375 },
1376 },
1377 ),
1378 Ok(
1379 Token {
1380 kind: String(
1381 Normal,
1382 ),
1383 span: Span {
1384 lo: 3,
1385 hi: 7,
1386 },
1387 },
1388 ),
1389 Ok(
1390 Token {
1391 kind: String(
1392 Interpolated(
1393 RBrace,
1394 Quote,
1395 ),
1396 ),
1397 span: Span {
1398 lo: 7,
1399 hi: 9,
1400 },
1401 },
1402 ),
1403 ]
1404 "#]],
1405 );
1406}
1407
1408#[test]
1409fn nested_interpolated_string() {
1410 check(
1411 r#"$"{$"{x}"}""#,
1412 &expect![[r#"
1413 [
1414 Ok(
1415 Token {
1416 kind: String(
1417 Interpolated(
1418 DollarQuote,
1419 LBrace,
1420 ),
1421 ),
1422 span: Span {
1423 lo: 0,
1424 hi: 3,
1425 },
1426 },
1427 ),
1428 Ok(
1429 Token {
1430 kind: String(
1431 Interpolated(
1432 DollarQuote,
1433 LBrace,
1434 ),
1435 ),
1436 span: Span {
1437 lo: 3,
1438 hi: 6,
1439 },
1440 },
1441 ),
1442 Ok(
1443 Token {
1444 kind: Ident,
1445 span: Span {
1446 lo: 6,
1447 hi: 7,
1448 },
1449 },
1450 ),
1451 Ok(
1452 Token {
1453 kind: String(
1454 Interpolated(
1455 RBrace,
1456 Quote,
1457 ),
1458 ),
1459 span: Span {
1460 lo: 7,
1461 hi: 9,
1462 },
1463 },
1464 ),
1465 Ok(
1466 Token {
1467 kind: String(
1468 Interpolated(
1469 RBrace,
1470 Quote,
1471 ),
1472 ),
1473 span: Span {
1474 lo: 9,
1475 hi: 11,
1476 },
1477 },
1478 ),
1479 ]
1480 "#]],
1481 );
1482}
1483
1484#[test]
1485fn nested_interpolated_string_with_exprs() {
1486 check(
1487 r#"$"foo {x + $"bar {y}"} baz""#,
1488 &expect![[r#"
1489 [
1490 Ok(
1491 Token {
1492 kind: String(
1493 Interpolated(
1494 DollarQuote,
1495 LBrace,
1496 ),
1497 ),
1498 span: Span {
1499 lo: 0,
1500 hi: 7,
1501 },
1502 },
1503 ),
1504 Ok(
1505 Token {
1506 kind: Ident,
1507 span: Span {
1508 lo: 7,
1509 hi: 8,
1510 },
1511 },
1512 ),
1513 Ok(
1514 Token {
1515 kind: ClosedBinOp(
1516 Plus,
1517 ),
1518 span: Span {
1519 lo: 9,
1520 hi: 10,
1521 },
1522 },
1523 ),
1524 Ok(
1525 Token {
1526 kind: String(
1527 Interpolated(
1528 DollarQuote,
1529 LBrace,
1530 ),
1531 ),
1532 span: Span {
1533 lo: 11,
1534 hi: 18,
1535 },
1536 },
1537 ),
1538 Ok(
1539 Token {
1540 kind: Ident,
1541 span: Span {
1542 lo: 18,
1543 hi: 19,
1544 },
1545 },
1546 ),
1547 Ok(
1548 Token {
1549 kind: String(
1550 Interpolated(
1551 RBrace,
1552 Quote,
1553 ),
1554 ),
1555 span: Span {
1556 lo: 19,
1557 hi: 21,
1558 },
1559 },
1560 ),
1561 Ok(
1562 Token {
1563 kind: String(
1564 Interpolated(
1565 RBrace,
1566 Quote,
1567 ),
1568 ),
1569 span: Span {
1570 lo: 21,
1571 hi: 27,
1572 },
1573 },
1574 ),
1575 ]
1576 "#]],
1577 );
1578}
1579
1580#[test]
1581fn unknown() {
1582 check(
1583 "##",
1584 &expect![[r#"
1585 [
1586 Err(
1587 Unknown(
1588 '#',
1589 Span {
1590 lo: 0,
1591 hi: 1,
1592 },
1593 ),
1594 ),
1595 Err(
1596 Unknown(
1597 '#',
1598 Span {
1599 lo: 1,
1600 hi: 2,
1601 },
1602 ),
1603 ),
1604 ]
1605 "#]],
1606 );
1607}
1608
1609#[test]
1610fn comment() {
1611 check(
1612 "//comment\nx",
1613 &expect![[r#"
1614 [
1615 Ok(
1616 Token {
1617 kind: Ident,
1618 span: Span {
1619 lo: 10,
1620 hi: 11,
1621 },
1622 },
1623 ),
1624 ]
1625 "#]],
1626 );
1627}
1628
1629#[test]
1630fn doc_comment() {
1631 check(
1632 "///comment\nx",
1633 &expect![[r#"
1634 [
1635 Ok(
1636 Token {
1637 kind: DocComment,
1638 span: Span {
1639 lo: 0,
1640 hi: 10,
1641 },
1642 },
1643 ),
1644 Ok(
1645 Token {
1646 kind: Ident,
1647 span: Span {
1648 lo: 11,
1649 hi: 12,
1650 },
1651 },
1652 ),
1653 ]
1654 "#]],
1655 );
1656}
1657
1658#[test]
1659fn comment_four_slashes() {
1660 check(
1661 "////comment\nx",
1662 &expect![[r#"
1663 [
1664 Ok(
1665 Token {
1666 kind: Ident,
1667 span: Span {
1668 lo: 12,
1669 hi: 13,
1670 },
1671 },
1672 ),
1673 ]
1674 "#]],
1675 );
1676}
1677
1678#[test]
1679fn unfinished_generic() {
1680 check(
1681 "' T",
1682 &expect![[r#"
1683 [
1684 Err(
1685 Incomplete(
1686 Ident,
1687 AposIdent,
1688 Whitespace,
1689 Span {
1690 lo: 1,
1691 hi: 3,
1692 },
1693 ),
1694 ),
1695 Ok(
1696 Token {
1697 kind: Ident,
1698 span: Span {
1699 lo: 3,
1700 hi: 4,
1701 },
1702 },
1703 ),
1704 ]
1705 "#]],
1706 );
1707}
1708#[test]
1709fn unfinished_generic_2() {
1710 check(
1711 "'// test
1712 T",
1713 &expect![[r#"
1714 [
1715 Err(
1716 Incomplete(
1717 Ident,
1718 AposIdent,
1719 Comment(
1720 Normal,
1721 ),
1722 Span {
1723 lo: 1,
1724 hi: 8,
1725 },
1726 ),
1727 ),
1728 Ok(
1729 Token {
1730 kind: Ident,
1731 span: Span {
1732 lo: 18,
1733 hi: 19,
1734 },
1735 },
1736 ),
1737 ]
1738 "#]],
1739 );
1740}
1741
1742#[test]
1743fn unfinished_generic_3() {
1744 check(
1745 "' T",
1746 &expect![[r#"
1747 [
1748 Err(
1749 Incomplete(
1750 Ident,
1751 AposIdent,
1752 Whitespace,
1753 Span {
1754 lo: 1,
1755 hi: 5,
1756 },
1757 ),
1758 ),
1759 Ok(
1760 Token {
1761 kind: Ident,
1762 span: Span {
1763 lo: 5,
1764 hi: 6,
1765 },
1766 },
1767 ),
1768 ]
1769 "#]],
1770 );
1771}
1772#[test]
1773fn correct_generic() {
1774 check(
1775 "'T",
1776 &expect![[r#"
1777 [
1778 Ok(
1779 Token {
1780 kind: AposIdent,
1781 span: Span {
1782 lo: 0,
1783 hi: 2,
1784 },
1785 },
1786 ),
1787 ]
1788 "#]],
1789 );
1790}
1791#[test]
1792fn generic_missing_ident() {
1793 check(
1794 "'",
1795 &expect![[r#"
1796 [
1797 Err(
1798 IncompleteEof(
1799 Ident,
1800 AposIdent,
1801 Span {
1802 lo: 1,
1803 hi: 1,
1804 },
1805 ),
1806 ),
1807 ]
1808 "#]],
1809 );
1810}
1811
1812#[test]
1813fn generic_underscore_name() {
1814 check(
1815 "'_",
1816 &expect![[r#"
1817 [
1818 Ok(
1819 Token {
1820 kind: AposIdent,
1821 span: Span {
1822 lo: 0,
1823 hi: 2,
1824 },
1825 },
1826 ),
1827 ]
1828 "#]],
1829 );
1830}
1831