]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_lexer/src/tests.rs
Auto merge of #99730 - lcnr:bound-vars-anon, r=jackh726
[rust.git] / compiler / rustc_lexer / src / tests.rs
1 use super::*;
2
3 use expect_test::{expect, Expect};
4
5 fn check_raw_str(s: &str, expected_hashes: u8, expected_err: Option<RawStrError>) {
6     let s = &format!("r{}", s);
7     let mut cursor = Cursor::new(s);
8     cursor.bump();
9     let (n_hashes, err) = cursor.raw_double_quoted_string(0);
10     assert_eq!(n_hashes, expected_hashes);
11     assert_eq!(err, expected_err);
12 }
13
14 #[test]
15 fn test_naked_raw_str() {
16     check_raw_str(r#""abc""#, 0, None);
17 }
18
19 #[test]
20 fn test_raw_no_start() {
21     check_raw_str(r##""abc"#"##, 0, None);
22 }
23
24 #[test]
25 fn test_too_many_terminators() {
26     // this error is handled in the parser later
27     check_raw_str(r###"#"abc"##"###, 1, None);
28 }
29
30 #[test]
31 fn test_unterminated() {
32     check_raw_str(
33         r#"#"abc"#,
34         1,
35         Some(RawStrError::NoTerminator { expected: 1, found: 0, possible_terminator_offset: None }),
36     );
37     check_raw_str(
38         r###"##"abc"#"###,
39         2,
40         Some(RawStrError::NoTerminator {
41             expected: 2,
42             found: 1,
43             possible_terminator_offset: Some(7),
44         }),
45     );
46     // We're looking for "# not just any #
47     check_raw_str(
48         r###"##"abc#"###,
49         2,
50         Some(RawStrError::NoTerminator { expected: 2, found: 0, possible_terminator_offset: None }),
51     )
52 }
53
54 #[test]
55 fn test_invalid_start() {
56     check_raw_str(r##"#~"abc"#"##, 1, Some(RawStrError::InvalidStarter { bad_char: '~' }));
57 }
58
59 #[test]
60 fn test_unterminated_no_pound() {
61     // https://github.com/rust-lang/rust/issues/70677
62     check_raw_str(
63         r#"""#,
64         0,
65         Some(RawStrError::NoTerminator { expected: 0, found: 0, possible_terminator_offset: None }),
66     );
67 }
68
69 #[test]
70 fn test_too_many_hashes() {
71     let max_count = u8::MAX;
72     let mut hashes: String = "#".repeat(max_count.into());
73
74     // Valid number of hashes (255 = 2^8 - 1 = u8::MAX), but invalid string.
75     check_raw_str(&hashes, max_count, Some(RawStrError::InvalidStarter { bad_char: '\u{0}' }));
76
77     // One more hash sign (256 = 2^8) becomes too many.
78     hashes.push('#');
79     check_raw_str(
80         &hashes,
81         0,
82         Some(RawStrError::TooManyDelimiters { found: usize::from(max_count) + 1 }),
83     );
84 }
85
86 #[test]
87 fn test_valid_shebang() {
88     // https://github.com/rust-lang/rust/issues/70528
89     let input = "#!/usr/bin/rustrun\nlet x = 5;";
90     assert_eq!(strip_shebang(input), Some(18));
91 }
92
93 #[test]
94 fn test_invalid_shebang_valid_rust_syntax() {
95     // https://github.com/rust-lang/rust/issues/70528
96     let input = "#!    [bad_attribute]";
97     assert_eq!(strip_shebang(input), None);
98 }
99
100 #[test]
101 fn test_shebang_second_line() {
102     // Because shebangs are interpreted by the kernel, they must be on the first line
103     let input = "\n#!/bin/bash";
104     assert_eq!(strip_shebang(input), None);
105 }
106
107 #[test]
108 fn test_shebang_space() {
109     let input = "#!    /bin/bash";
110     assert_eq!(strip_shebang(input), Some(input.len()));
111 }
112
113 #[test]
114 fn test_shebang_empty_shebang() {
115     let input = "#!    \n[attribute(foo)]";
116     assert_eq!(strip_shebang(input), None);
117 }
118
119 #[test]
120 fn test_invalid_shebang_comment() {
121     let input = "#!//bin/ami/a/comment\n[";
122     assert_eq!(strip_shebang(input), None)
123 }
124
125 #[test]
126 fn test_invalid_shebang_another_comment() {
127     let input = "#!/*bin/ami/a/comment*/\n[attribute";
128     assert_eq!(strip_shebang(input), None)
129 }
130
131 #[test]
132 fn test_shebang_valid_rust_after() {
133     let input = "#!/*bin/ami/a/comment*/\npub fn main() {}";
134     assert_eq!(strip_shebang(input), Some(23))
135 }
136
137 #[test]
138 fn test_shebang_followed_by_attrib() {
139     let input = "#!/bin/rust-scripts\n#![allow_unused(true)]";
140     assert_eq!(strip_shebang(input), Some(19));
141 }
142
143 fn check_lexing(src: &str, expect: Expect) {
144     let actual: String = tokenize(src).map(|token| format!("{:?}\n", token)).collect();
145     expect.assert_eq(&actual)
146 }
147
148 #[test]
149 fn smoke_test() {
150     check_lexing(
151         "/* my source file */ fn main() { println!(\"zebra\"); }\n",
152         expect![[r#"
153             Token { kind: BlockComment { doc_style: None, terminated: true }, len: 20 }
154             Token { kind: Whitespace, len: 1 }
155             Token { kind: Ident, len: 2 }
156             Token { kind: Whitespace, len: 1 }
157             Token { kind: Ident, len: 4 }
158             Token { kind: OpenParen, len: 1 }
159             Token { kind: CloseParen, len: 1 }
160             Token { kind: Whitespace, len: 1 }
161             Token { kind: OpenBrace, len: 1 }
162             Token { kind: Whitespace, len: 1 }
163             Token { kind: Ident, len: 7 }
164             Token { kind: Bang, len: 1 }
165             Token { kind: OpenParen, len: 1 }
166             Token { kind: Literal { kind: Str { terminated: true }, suffix_start: 7 }, len: 7 }
167             Token { kind: CloseParen, len: 1 }
168             Token { kind: Semi, len: 1 }
169             Token { kind: Whitespace, len: 1 }
170             Token { kind: CloseBrace, len: 1 }
171             Token { kind: Whitespace, len: 1 }
172         "#]],
173     )
174 }
175
176 #[test]
177 fn comment_flavors() {
178     check_lexing(
179         r"
180 // line
181 //// line as well
182 /// outer doc line
183 //! inner doc line
184 /* block */
185 /**/
186 /*** also block */
187 /** outer doc block */
188 /*! inner doc block */
189 ",
190         expect![[r#"
191             Token { kind: Whitespace, len: 1 }
192             Token { kind: LineComment { doc_style: None }, len: 7 }
193             Token { kind: Whitespace, len: 1 }
194             Token { kind: LineComment { doc_style: None }, len: 17 }
195             Token { kind: Whitespace, len: 1 }
196             Token { kind: LineComment { doc_style: Some(Outer) }, len: 18 }
197             Token { kind: Whitespace, len: 1 }
198             Token { kind: LineComment { doc_style: Some(Inner) }, len: 18 }
199             Token { kind: Whitespace, len: 1 }
200             Token { kind: BlockComment { doc_style: None, terminated: true }, len: 11 }
201             Token { kind: Whitespace, len: 1 }
202             Token { kind: BlockComment { doc_style: None, terminated: true }, len: 4 }
203             Token { kind: Whitespace, len: 1 }
204             Token { kind: BlockComment { doc_style: None, terminated: true }, len: 18 }
205             Token { kind: Whitespace, len: 1 }
206             Token { kind: BlockComment { doc_style: Some(Outer), terminated: true }, len: 22 }
207             Token { kind: Whitespace, len: 1 }
208             Token { kind: BlockComment { doc_style: Some(Inner), terminated: true }, len: 22 }
209             Token { kind: Whitespace, len: 1 }
210         "#]],
211     )
212 }
213
214 #[test]
215 fn nested_block_comments() {
216     check_lexing(
217         "/* /* */ */'a'",
218         expect![[r#"
219             Token { kind: BlockComment { doc_style: None, terminated: true }, len: 11 }
220             Token { kind: Literal { kind: Char { terminated: true }, suffix_start: 3 }, len: 3 }
221         "#]],
222     )
223 }
224
225 #[test]
226 fn characters() {
227     check_lexing(
228         "'a' ' ' '\\n'",
229         expect![[r#"
230             Token { kind: Literal { kind: Char { terminated: true }, suffix_start: 3 }, len: 3 }
231             Token { kind: Whitespace, len: 1 }
232             Token { kind: Literal { kind: Char { terminated: true }, suffix_start: 3 }, len: 3 }
233             Token { kind: Whitespace, len: 1 }
234             Token { kind: Literal { kind: Char { terminated: true }, suffix_start: 4 }, len: 4 }
235         "#]],
236     );
237 }
238
239 #[test]
240 fn lifetime() {
241     check_lexing(
242         "'abc",
243         expect![[r#"
244             Token { kind: Lifetime { starts_with_number: false }, len: 4 }
245         "#]],
246     );
247 }
248
249 #[test]
250 fn raw_string() {
251     check_lexing(
252         "r###\"\"#a\\b\x00c\"\"###",
253         expect![[r#"
254             Token { kind: Literal { kind: RawStr { n_hashes: 3, err: None }, suffix_start: 17 }, len: 17 }
255         "#]],
256     )
257 }
258
259 #[test]
260 fn literal_suffixes() {
261     check_lexing(
262         r####"
263 'a'
264 b'a'
265 "a"
266 b"a"
267 1234
268 0b101
269 0xABC
270 1.0
271 1.0e10
272 2us
273 r###"raw"###suffix
274 br###"raw"###suffix
275 "####,
276         expect![[r#"
277             Token { kind: Whitespace, len: 1 }
278             Token { kind: Literal { kind: Char { terminated: true }, suffix_start: 3 }, len: 3 }
279             Token { kind: Whitespace, len: 1 }
280             Token { kind: Literal { kind: Byte { terminated: true }, suffix_start: 4 }, len: 4 }
281             Token { kind: Whitespace, len: 1 }
282             Token { kind: Literal { kind: Str { terminated: true }, suffix_start: 3 }, len: 3 }
283             Token { kind: Whitespace, len: 1 }
284             Token { kind: Literal { kind: ByteStr { terminated: true }, suffix_start: 4 }, len: 4 }
285             Token { kind: Whitespace, len: 1 }
286             Token { kind: Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 4 }, len: 4 }
287             Token { kind: Whitespace, len: 1 }
288             Token { kind: Literal { kind: Int { base: Binary, empty_int: false }, suffix_start: 5 }, len: 5 }
289             Token { kind: Whitespace, len: 1 }
290             Token { kind: Literal { kind: Int { base: Hexadecimal, empty_int: false }, suffix_start: 5 }, len: 5 }
291             Token { kind: Whitespace, len: 1 }
292             Token { kind: Literal { kind: Float { base: Decimal, empty_exponent: false }, suffix_start: 3 }, len: 3 }
293             Token { kind: Whitespace, len: 1 }
294             Token { kind: Literal { kind: Float { base: Decimal, empty_exponent: false }, suffix_start: 6 }, len: 6 }
295             Token { kind: Whitespace, len: 1 }
296             Token { kind: Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 }, len: 3 }
297             Token { kind: Whitespace, len: 1 }
298             Token { kind: Literal { kind: RawStr { n_hashes: 3, err: None }, suffix_start: 12 }, len: 18 }
299             Token { kind: Whitespace, len: 1 }
300             Token { kind: Literal { kind: RawByteStr { n_hashes: 3, err: None }, suffix_start: 13 }, len: 19 }
301             Token { kind: Whitespace, len: 1 }
302         "#]],
303     )
304 }