3 use expect_test::{expect, Expect};
5 fn check_raw_str(s: &str, expected_hashes: u16, expected_err: Option<RawStrError>) {
6 let s = &format!("r{}", s);
7 let mut cursor = Cursor::new(s);
9 let (n_hashes, err) = cursor.raw_double_quoted_string(0);
10 assert_eq!(n_hashes, expected_hashes);
11 assert_eq!(err, expected_err);
15 fn test_naked_raw_str() {
16 check_raw_str(r#""abc""#, 0, None);
20 fn test_raw_no_start() {
21 check_raw_str(r##""abc"#"##, 0, None);
25 fn test_too_many_terminators() {
26 // this error is handled in the parser later
27 check_raw_str(r###"#"abc"##"###, 1, None);
31 fn test_unterminated() {
35 Some(RawStrError::NoTerminator { expected: 1, found: 0, possible_terminator_offset: None }),
40 Some(RawStrError::NoTerminator {
43 possible_terminator_offset: Some(7),
46 // We're looking for "# not just any #
50 Some(RawStrError::NoTerminator { expected: 2, found: 0, possible_terminator_offset: None }),
55 fn test_invalid_start() {
56 check_raw_str(r##"#~"abc"#"##, 1, Some(RawStrError::InvalidStarter { bad_char: '~' }));
60 fn test_unterminated_no_pound() {
61 // https://github.com/rust-lang/rust/issues/70677
65 Some(RawStrError::NoTerminator { expected: 0, found: 0, possible_terminator_offset: None }),
70 fn test_valid_shebang() {
71 // https://github.com/rust-lang/rust/issues/70528
72 let input = "#!/usr/bin/rustrun\nlet x = 5;";
73 assert_eq!(strip_shebang(input), Some(18));
77 fn test_invalid_shebang_valid_rust_syntax() {
78 // https://github.com/rust-lang/rust/issues/70528
79 let input = "#! [bad_attribute]";
80 assert_eq!(strip_shebang(input), None);
84 fn test_shebang_second_line() {
85 // Because shebangs are interpreted by the kernel, they must be on the first line
86 let input = "\n#!/bin/bash";
87 assert_eq!(strip_shebang(input), None);
91 fn test_shebang_space() {
92 let input = "#! /bin/bash";
93 assert_eq!(strip_shebang(input), Some(input.len()));
97 fn test_shebang_empty_shebang() {
98 let input = "#! \n[attribute(foo)]";
99 assert_eq!(strip_shebang(input), None);
103 fn test_invalid_shebang_comment() {
104 let input = "#!//bin/ami/a/comment\n[";
105 assert_eq!(strip_shebang(input), None)
109 fn test_invalid_shebang_another_comment() {
110 let input = "#!/*bin/ami/a/comment*/\n[attribute";
111 assert_eq!(strip_shebang(input), None)
115 fn test_shebang_valid_rust_after() {
116 let input = "#!/*bin/ami/a/comment*/\npub fn main() {}";
117 assert_eq!(strip_shebang(input), Some(23))
121 fn test_shebang_followed_by_attrib() {
122 let input = "#!/bin/rust-scripts\n#![allow_unused(true)]";
123 assert_eq!(strip_shebang(input), Some(19));
126 fn check_lexing(src: &str, expect: Expect) {
127 let actual: String = tokenize(src).map(|token| format!("{:?}\n", token)).collect();
128 expect.assert_eq(&actual)
134 "/* my source file */ fn main() { println!(\"zebra\"); }\n",
136 Token { kind: BlockComment { doc_style: None, terminated: true }, len: 20 }
137 Token { kind: Whitespace, len: 1 }
138 Token { kind: Ident, len: 2 }
139 Token { kind: Whitespace, len: 1 }
140 Token { kind: Ident, len: 4 }
141 Token { kind: OpenParen, len: 1 }
142 Token { kind: CloseParen, len: 1 }
143 Token { kind: Whitespace, len: 1 }
144 Token { kind: OpenBrace, len: 1 }
145 Token { kind: Whitespace, len: 1 }
146 Token { kind: Ident, len: 7 }
147 Token { kind: Bang, len: 1 }
148 Token { kind: OpenParen, len: 1 }
149 Token { kind: Literal { kind: Str { terminated: true }, suffix_start: 7 }, len: 7 }
150 Token { kind: CloseParen, len: 1 }
151 Token { kind: Semi, len: 1 }
152 Token { kind: Whitespace, len: 1 }
153 Token { kind: CloseBrace, len: 1 }
154 Token { kind: Whitespace, len: 1 }
160 fn comment_flavors() {
170 /** outer doc block */
171 /*! inner doc block */
174 Token { kind: Whitespace, len: 1 }
175 Token { kind: LineComment { doc_style: None }, len: 7 }
176 Token { kind: Whitespace, len: 1 }
177 Token { kind: LineComment { doc_style: None }, len: 17 }
178 Token { kind: Whitespace, len: 1 }
179 Token { kind: LineComment { doc_style: Some(Outer) }, len: 18 }
180 Token { kind: Whitespace, len: 1 }
181 Token { kind: LineComment { doc_style: Some(Inner) }, len: 18 }
182 Token { kind: Whitespace, len: 1 }
183 Token { kind: BlockComment { doc_style: None, terminated: true }, len: 11 }
184 Token { kind: Whitespace, len: 1 }
185 Token { kind: BlockComment { doc_style: None, terminated: true }, len: 4 }
186 Token { kind: Whitespace, len: 1 }
187 Token { kind: BlockComment { doc_style: None, terminated: true }, len: 18 }
188 Token { kind: Whitespace, len: 1 }
189 Token { kind: BlockComment { doc_style: Some(Outer), terminated: true }, len: 22 }
190 Token { kind: Whitespace, len: 1 }
191 Token { kind: BlockComment { doc_style: Some(Inner), terminated: true }, len: 22 }
192 Token { kind: Whitespace, len: 1 }
198 fn nested_block_comments() {
202 Token { kind: BlockComment { doc_style: None, terminated: true }, len: 11 }
203 Token { kind: Literal { kind: Char { terminated: true }, suffix_start: 3 }, len: 3 }
213 Token { kind: Literal { kind: Char { terminated: true }, suffix_start: 3 }, len: 3 }
214 Token { kind: Whitespace, len: 1 }
215 Token { kind: Literal { kind: Char { terminated: true }, suffix_start: 3 }, len: 3 }
216 Token { kind: Whitespace, len: 1 }
217 Token { kind: Literal { kind: Char { terminated: true }, suffix_start: 4 }, len: 4 }
227 Token { kind: Lifetime { starts_with_number: false }, len: 4 }
235 "r###\"\"#a\\b\x00c\"\"###",
237 Token { kind: Literal { kind: RawStr { n_hashes: 3, err: None }, suffix_start: 17 }, len: 17 }
243 fn literal_suffixes() {
260 Token { kind: Whitespace, len: 1 }
261 Token { kind: Literal { kind: Char { terminated: true }, suffix_start: 3 }, len: 3 }
262 Token { kind: Whitespace, len: 1 }
263 Token { kind: Literal { kind: Byte { terminated: true }, suffix_start: 4 }, len: 4 }
264 Token { kind: Whitespace, len: 1 }
265 Token { kind: Literal { kind: Str { terminated: true }, suffix_start: 3 }, len: 3 }
266 Token { kind: Whitespace, len: 1 }
267 Token { kind: Literal { kind: ByteStr { terminated: true }, suffix_start: 4 }, len: 4 }
268 Token { kind: Whitespace, len: 1 }
269 Token { kind: Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 4 }, len: 4 }
270 Token { kind: Whitespace, len: 1 }
271 Token { kind: Literal { kind: Int { base: Binary, empty_int: false }, suffix_start: 5 }, len: 5 }
272 Token { kind: Whitespace, len: 1 }
273 Token { kind: Literal { kind: Int { base: Hexadecimal, empty_int: false }, suffix_start: 5 }, len: 5 }
274 Token { kind: Whitespace, len: 1 }
275 Token { kind: Literal { kind: Float { base: Decimal, empty_exponent: false }, suffix_start: 3 }, len: 3 }
276 Token { kind: Whitespace, len: 1 }
277 Token { kind: Literal { kind: Float { base: Decimal, empty_exponent: false }, suffix_start: 6 }, len: 6 }
278 Token { kind: Whitespace, len: 1 }
279 Token { kind: Literal { kind: Int { base: Decimal, empty_int: false }, suffix_start: 1 }, len: 3 }
280 Token { kind: Whitespace, len: 1 }
281 Token { kind: Literal { kind: RawStr { n_hashes: 3, err: None }, suffix_start: 12 }, len: 18 }
282 Token { kind: Whitespace, len: 1 }
283 Token { kind: Literal { kind: RawByteStr { n_hashes: 3, err: None }, suffix_start: 13 }, len: 19 }
284 Token { kind: Whitespace, len: 1 }