]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_span/src/source_map/tests.rs
New upstream version 1.51.0+dfsg1
[rustc.git] / compiler / rustc_span / src / source_map / tests.rs
CommitLineData
416331ca
XL
1use super::*;
2
3use rustc_data_structures::sync::Lrc;
4
5fn init_source_map() -> SourceMap {
6 let sm = SourceMap::new(FilePathMapping::empty());
dfeec247
XL
7 sm.new_source_file(PathBuf::from("blork.rs").into(), "first line.\nsecond line".to_string());
8 sm.new_source_file(PathBuf::from("empty.rs").into(), String::new());
9 sm.new_source_file(PathBuf::from("blork2.rs").into(), "first line.\nsecond line".to_string());
416331ca
XL
10 sm
11}
12
e1599b0c 13/// Tests `lookup_byte_offset`.
416331ca
XL
14#[test]
15fn t3() {
416331ca
XL
16 let sm = init_source_map();
17
18 let srcfbp1 = sm.lookup_byte_offset(BytePos(23));
19 assert_eq!(srcfbp1.sf.name, PathBuf::from("blork.rs").into());
20 assert_eq!(srcfbp1.pos, BytePos(23));
21
22 let srcfbp1 = sm.lookup_byte_offset(BytePos(24));
23 assert_eq!(srcfbp1.sf.name, PathBuf::from("empty.rs").into());
24 assert_eq!(srcfbp1.pos, BytePos(0));
25
26 let srcfbp2 = sm.lookup_byte_offset(BytePos(25));
27 assert_eq!(srcfbp2.sf.name, PathBuf::from("blork2.rs").into());
28 assert_eq!(srcfbp2.pos, BytePos(0));
29}
30
e1599b0c 31/// Tests `bytepos_to_file_charpos`.
416331ca
XL
32#[test]
33fn t4() {
416331ca
XL
34 let sm = init_source_map();
35
36 let cp1 = sm.bytepos_to_file_charpos(BytePos(22));
37 assert_eq!(cp1, CharPos(22));
38
39 let cp2 = sm.bytepos_to_file_charpos(BytePos(25));
40 assert_eq!(cp2, CharPos(0));
41}
42
e1599b0c 43/// Tests zero-length `SourceFile`s.
416331ca
XL
44#[test]
45fn t5() {
416331ca
XL
46 let sm = init_source_map();
47
48 let loc1 = sm.lookup_char_pos(BytePos(22));
49 assert_eq!(loc1.file.name, PathBuf::from("blork.rs").into());
50 assert_eq!(loc1.line, 2);
51 assert_eq!(loc1.col, CharPos(10));
52
53 let loc2 = sm.lookup_char_pos(BytePos(25));
54 assert_eq!(loc2.file.name, PathBuf::from("blork2.rs").into());
55 assert_eq!(loc2.line, 1);
56 assert_eq!(loc2.col, CharPos(0));
57}
58
59fn init_source_map_mbc() -> SourceMap {
60 let sm = SourceMap::new(FilePathMapping::empty());
e1599b0c 61 // "€" is a three-byte UTF8 char.
dfeec247
XL
62 sm.new_source_file(
63 PathBuf::from("blork.rs").into(),
64 "fir€st €€€€ line.\nsecond line".to_string(),
65 );
66 sm.new_source_file(
67 PathBuf::from("blork2.rs").into(),
68 "first line€€.\n€ second line".to_string(),
69 );
416331ca
XL
70 sm
71}
72
e1599b0c 73/// Tests `bytepos_to_file_charpos` in the presence of multi-byte chars.
416331ca
XL
74#[test]
75fn t6() {
416331ca
XL
76 let sm = init_source_map_mbc();
77
78 let cp1 = sm.bytepos_to_file_charpos(BytePos(3));
79 assert_eq!(cp1, CharPos(3));
80
81 let cp2 = sm.bytepos_to_file_charpos(BytePos(6));
82 assert_eq!(cp2, CharPos(4));
83
84 let cp3 = sm.bytepos_to_file_charpos(BytePos(56));
85 assert_eq!(cp3, CharPos(12));
86
87 let cp4 = sm.bytepos_to_file_charpos(BytePos(61));
88 assert_eq!(cp4, CharPos(15));
89}
90
e1599b0c 91/// Test `span_to_lines` for a span ending at the end of a `SourceFile`.
416331ca
XL
92#[test]
93fn t7() {
416331ca 94 let sm = init_source_map();
e1599b0c 95 let span = Span::with_root_ctxt(BytePos(12), BytePos(23));
416331ca
XL
96 let file_lines = sm.span_to_lines(span).unwrap();
97
98 assert_eq!(file_lines.file.name, PathBuf::from("blork.rs").into());
99 assert_eq!(file_lines.lines.len(), 1);
100 assert_eq!(file_lines.lines[0].line_index, 1);
101}
102
103/// Given a string like " ~~~~~~~~~~~~ ", produces a span
104/// converting that range. The idea is that the string has the same
105/// length as the input, and we uncover the byte positions. Note
106/// that this can span lines and so on.
107fn span_from_selection(input: &str, selection: &str) -> Span {
108 assert_eq!(input.len(), selection.len());
109 let left_index = selection.find('~').unwrap() as u32;
5869c6ff 110 let right_index = selection.rfind('~').map_or(left_index, |x| x as u32);
e1599b0c 111 Span::with_root_ctxt(BytePos(left_index), BytePos(right_index + 1))
416331ca
XL
112}
113
e1599b0c 114/// Tests `span_to_snippet` and `span_to_lines` for a span converting 3
416331ca
XL
115/// lines in the middle of a file.
116#[test]
117fn span_to_snippet_and_lines_spanning_multiple_lines() {
118 let sm = SourceMap::new(FilePathMapping::empty());
119 let inputtext = "aaaaa\nbbbbBB\nCCC\nDDDDDddddd\neee\n";
120 let selection = " \n ~~\n~~~\n~~~~~ \n \n";
121 sm.new_source_file(Path::new("blork.rs").to_owned().into(), inputtext.to_string());
122 let span = span_from_selection(inputtext, selection);
123
e1599b0c 124 // Check that we are extracting the text we thought we were extracting.
416331ca
XL
125 assert_eq!(&sm.span_to_snippet(span).unwrap(), "BB\nCCC\nDDDDD");
126
e1599b0c 127 // Check that span_to_lines gives us the complete result with the lines/cols we expected.
416331ca
XL
128 let lines = sm.span_to_lines(span).unwrap();
129 let expected = vec![
130 LineInfo { line_index: 1, start_col: CharPos(4), end_col: CharPos(6) },
131 LineInfo { line_index: 2, start_col: CharPos(0), end_col: CharPos(3) },
dfeec247
XL
132 LineInfo { line_index: 3, start_col: CharPos(0), end_col: CharPos(5) },
133 ];
416331ca
XL
134 assert_eq!(lines.lines, expected);
135}
136
e1599b0c 137/// Test span_to_snippet for a span ending at the end of a `SourceFile`.
416331ca
XL
138#[test]
139fn t8() {
416331ca 140 let sm = init_source_map();
e1599b0c 141 let span = Span::with_root_ctxt(BytePos(12), BytePos(23));
416331ca
XL
142 let snippet = sm.span_to_snippet(span);
143
144 assert_eq!(snippet, Ok("second line".to_string()));
145}
146
e1599b0c 147/// Test `span_to_str` for a span ending at the end of a `SourceFile`.
416331ca
XL
148#[test]
149fn t9() {
416331ca 150 let sm = init_source_map();
e1599b0c 151 let span = Span::with_root_ctxt(BytePos(12), BytePos(23));
dfeec247 152 let sstr = sm.span_to_string(span);
416331ca
XL
153
154 assert_eq!(sstr, "blork.rs:2:1: 2:12");
155}
156
e1599b0c 157/// Tests failing to merge two spans on different lines.
416331ca
XL
158#[test]
159fn span_merging_fail() {
160 let sm = SourceMap::new(FilePathMapping::empty());
dfeec247 161 let inputtext = "bbbb BB\ncc CCC\n";
416331ca
XL
162 let selection1 = " ~~\n \n";
163 let selection2 = " \n ~~~\n";
164 sm.new_source_file(Path::new("blork.rs").to_owned().into(), inputtext.to_owned());
165 let span1 = span_from_selection(inputtext, selection1);
166 let span2 = span_from_selection(inputtext, selection2);
167
168 assert!(sm.merge_spans(span1, span2).is_none());
169}
170
ba9703b0
XL
171/// Tests loading an external source file that requires normalization.
172#[test]
173fn t10() {
174 let sm = SourceMap::new(FilePathMapping::empty());
175 let unnormalized = "first line.\r\nsecond line";
176 let normalized = "first line.\nsecond line";
177
178 let src_file = sm.new_source_file(PathBuf::from("blork.rs").into(), unnormalized.to_string());
179
180 assert_eq!(src_file.src.as_ref().unwrap().as_ref(), normalized);
181 assert!(
182 src_file.src_hash.matches(unnormalized),
183 "src_hash should use the source before normalization"
184 );
185
186 let SourceFile {
187 name,
188 name_was_remapped,
189 src_hash,
190 start_pos,
191 end_pos,
192 lines,
193 multibyte_chars,
194 non_narrow_chars,
195 normalized_pos,
196 name_hash,
197 ..
198 } = (*src_file).clone();
199
200 let imported_src_file = sm.new_imported_source_file(
201 name,
202 name_was_remapped,
203 src_hash,
204 name_hash,
205 (end_pos - start_pos).to_usize(),
206 CrateNum::new(0),
207 lines,
208 multibyte_chars,
209 non_narrow_chars,
210 normalized_pos,
211 start_pos,
212 end_pos,
213 );
214
215 assert!(
216 imported_src_file.external_src.borrow().get_source().is_none(),
217 "imported source file should not have source yet"
218 );
219 imported_src_file.add_external_src(|| Some(unnormalized.to_string()));
220 assert_eq!(
221 imported_src_file.external_src.borrow().get_source().unwrap().as_ref(),
222 normalized,
223 "imported source file should be normalized"
224 );
225}
226
e1599b0c 227/// Returns the span corresponding to the `n`th occurrence of `substring` in `source_text`.
416331ca 228trait SourceMapExtension {
e1599b0c
XL
229 fn span_substr(
230 &self,
231 file: &Lrc<SourceFile>,
232 source_text: &str,
233 substring: &str,
234 n: usize,
235 ) -> Span;
416331ca
XL
236}
237
238impl SourceMapExtension for SourceMap {
e1599b0c
XL
239 fn span_substr(
240 &self,
241 file: &Lrc<SourceFile>,
242 source_text: &str,
243 substring: &str,
244 n: usize,
245 ) -> Span {
246 println!(
247 "span_substr(file={:?}/{:?}, substring={:?}, n={})",
248 file.name, file.start_pos, substring, n
249 );
416331ca
XL
250 let mut i = 0;
251 let mut hi = 0;
252 loop {
253 let offset = source_text[hi..].find(substring).unwrap_or_else(|| {
e1599b0c
XL
254 panic!(
255 "source_text `{}` does not have {} occurrences of `{}`, only {}",
256 source_text, n, substring, i
257 );
416331ca
XL
258 });
259 let lo = hi + offset;
260 hi = lo + substring.len();
261 if i == n {
e1599b0c 262 let span = Span::with_root_ctxt(
416331ca
XL
263 BytePos(lo as u32 + file.start_pos.0),
264 BytePos(hi as u32 + file.start_pos.0),
416331ca 265 );
e1599b0c 266 assert_eq!(&self.span_to_snippet(span).unwrap()[..], substring);
416331ca
XL
267 return span;
268 }
269 i += 1;
270 }
271 }
272}