]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/source_map/tests.rs
bump smallvec to 1.0
[rust.git] / src / libsyntax / source_map / tests.rs
1 use super::*;
2
3 use rustc_data_structures::sync::Lrc;
4
5 fn init_source_map() -> SourceMap {
6     let sm = SourceMap::new(FilePathMapping::empty());
7     sm.new_source_file(
8         PathBuf::from("blork.rs").into(),
9         "first line.\nsecond line".to_string(),
10     );
11     sm.new_source_file(
12         PathBuf::from("empty.rs").into(),
13         String::new(),
14     );
15     sm.new_source_file(
16         PathBuf::from("blork2.rs").into(),
17         "first line.\nsecond line".to_string(),
18     );
19     sm
20 }
21
22 /// Tests `lookup_byte_offset`.
23 #[test]
24 fn t3() {
25     let sm = init_source_map();
26
27     let srcfbp1 = sm.lookup_byte_offset(BytePos(23));
28     assert_eq!(srcfbp1.sf.name, PathBuf::from("blork.rs").into());
29     assert_eq!(srcfbp1.pos, BytePos(23));
30
31     let srcfbp1 = sm.lookup_byte_offset(BytePos(24));
32     assert_eq!(srcfbp1.sf.name, PathBuf::from("empty.rs").into());
33     assert_eq!(srcfbp1.pos, BytePos(0));
34
35     let srcfbp2 = sm.lookup_byte_offset(BytePos(25));
36     assert_eq!(srcfbp2.sf.name, PathBuf::from("blork2.rs").into());
37     assert_eq!(srcfbp2.pos, BytePos(0));
38 }
39
40 /// Tests `bytepos_to_file_charpos`.
41 #[test]
42 fn t4() {
43     let sm = init_source_map();
44
45     let cp1 = sm.bytepos_to_file_charpos(BytePos(22));
46     assert_eq!(cp1, CharPos(22));
47
48     let cp2 = sm.bytepos_to_file_charpos(BytePos(25));
49     assert_eq!(cp2, CharPos(0));
50 }
51
52 /// Tests zero-length `SourceFile`s.
53 #[test]
54 fn t5() {
55     let sm = init_source_map();
56
57     let loc1 = sm.lookup_char_pos(BytePos(22));
58     assert_eq!(loc1.file.name, PathBuf::from("blork.rs").into());
59     assert_eq!(loc1.line, 2);
60     assert_eq!(loc1.col, CharPos(10));
61
62     let loc2 = sm.lookup_char_pos(BytePos(25));
63     assert_eq!(loc2.file.name, PathBuf::from("blork2.rs").into());
64     assert_eq!(loc2.line, 1);
65     assert_eq!(loc2.col, CharPos(0));
66 }
67
68 fn init_source_map_mbc() -> SourceMap {
69     let sm = SourceMap::new(FilePathMapping::empty());
70     // "€" is a three-byte UTF8 char.
71     sm.new_source_file(PathBuf::from("blork.rs").into(),
72                     "fir€st €€€€ line.\nsecond line".to_string());
73     sm.new_source_file(PathBuf::from("blork2.rs").into(),
74                     "first line€€.\n€ second line".to_string());
75     sm
76 }
77
78 /// Tests `bytepos_to_file_charpos` in the presence of multi-byte chars.
79 #[test]
80 fn t6() {
81     let sm = init_source_map_mbc();
82
83     let cp1 = sm.bytepos_to_file_charpos(BytePos(3));
84     assert_eq!(cp1, CharPos(3));
85
86     let cp2 = sm.bytepos_to_file_charpos(BytePos(6));
87     assert_eq!(cp2, CharPos(4));
88
89     let cp3 = sm.bytepos_to_file_charpos(BytePos(56));
90     assert_eq!(cp3, CharPos(12));
91
92     let cp4 = sm.bytepos_to_file_charpos(BytePos(61));
93     assert_eq!(cp4, CharPos(15));
94 }
95
96 /// Test `span_to_lines` for a span ending at the end of a `SourceFile`.
97 #[test]
98 fn t7() {
99     let sm = init_source_map();
100     let span = Span::with_root_ctxt(BytePos(12), BytePos(23));
101     let file_lines = sm.span_to_lines(span).unwrap();
102
103     assert_eq!(file_lines.file.name, PathBuf::from("blork.rs").into());
104     assert_eq!(file_lines.lines.len(), 1);
105     assert_eq!(file_lines.lines[0].line_index, 1);
106 }
107
108 /// Given a string like " ~~~~~~~~~~~~ ", produces a span
109 /// converting that range. The idea is that the string has the same
110 /// length as the input, and we uncover the byte positions. Note
111 /// that this can span lines and so on.
112 fn span_from_selection(input: &str, selection: &str) -> Span {
113     assert_eq!(input.len(), selection.len());
114     let left_index = selection.find('~').unwrap() as u32;
115     let right_index = selection.rfind('~').map(|x|x as u32).unwrap_or(left_index);
116     Span::with_root_ctxt(BytePos(left_index), BytePos(right_index + 1))
117 }
118
119 /// Tests `span_to_snippet` and `span_to_lines` for a span converting 3
120 /// lines in the middle of a file.
121 #[test]
122 fn span_to_snippet_and_lines_spanning_multiple_lines() {
123     let sm = SourceMap::new(FilePathMapping::empty());
124     let inputtext = "aaaaa\nbbbbBB\nCCC\nDDDDDddddd\neee\n";
125     let selection = "     \n    ~~\n~~~\n~~~~~     \n   \n";
126     sm.new_source_file(Path::new("blork.rs").to_owned().into(), inputtext.to_string());
127     let span = span_from_selection(inputtext, selection);
128
129     // Check that we are extracting the text we thought we were extracting.
130     assert_eq!(&sm.span_to_snippet(span).unwrap(), "BB\nCCC\nDDDDD");
131
132     // Check that span_to_lines gives us the complete result with the lines/cols we expected.
133     let lines = sm.span_to_lines(span).unwrap();
134     let expected = vec![
135         LineInfo { line_index: 1, start_col: CharPos(4), end_col: CharPos(6) },
136         LineInfo { line_index: 2, start_col: CharPos(0), end_col: CharPos(3) },
137         LineInfo { line_index: 3, start_col: CharPos(0), end_col: CharPos(5) }
138         ];
139     assert_eq!(lines.lines, expected);
140 }
141
142 /// Test span_to_snippet for a span ending at the end of a `SourceFile`.
143 #[test]
144 fn t8() {
145     let sm = init_source_map();
146     let span = Span::with_root_ctxt(BytePos(12), BytePos(23));
147     let snippet = sm.span_to_snippet(span);
148
149     assert_eq!(snippet, Ok("second line".to_string()));
150 }
151
152 /// Test `span_to_str` for a span ending at the end of a `SourceFile`.
153 #[test]
154 fn t9() {
155     let sm = init_source_map();
156     let span = Span::with_root_ctxt(BytePos(12), BytePos(23));
157     let sstr =  sm.span_to_string(span);
158
159     assert_eq!(sstr, "blork.rs:2:1: 2:12");
160 }
161
162 /// Tests failing to merge two spans on different lines.
163 #[test]
164 fn span_merging_fail() {
165     let sm = SourceMap::new(FilePathMapping::empty());
166     let inputtext  = "bbbb BB\ncc CCC\n";
167     let selection1 = "     ~~\n      \n";
168     let selection2 = "       \n   ~~~\n";
169     sm.new_source_file(Path::new("blork.rs").to_owned().into(), inputtext.to_owned());
170     let span1 = span_from_selection(inputtext, selection1);
171     let span2 = span_from_selection(inputtext, selection2);
172
173     assert!(sm.merge_spans(span1, span2).is_none());
174 }
175
176 /// Returns the span corresponding to the `n`th occurrence of `substring` in `source_text`.
177 trait SourceMapExtension {
178     fn span_substr(
179         &self,
180         file: &Lrc<SourceFile>,
181         source_text: &str,
182         substring: &str,
183         n: usize,
184     ) -> Span;
185 }
186
187 impl SourceMapExtension for SourceMap {
188     fn span_substr(
189         &self,
190         file: &Lrc<SourceFile>,
191         source_text: &str,
192         substring: &str,
193         n: usize,
194     ) -> Span {
195         println!(
196             "span_substr(file={:?}/{:?}, substring={:?}, n={})",
197             file.name, file.start_pos, substring, n
198         );
199         let mut i = 0;
200         let mut hi = 0;
201         loop {
202             let offset = source_text[hi..].find(substring).unwrap_or_else(|| {
203                 panic!(
204                     "source_text `{}` does not have {} occurrences of `{}`, only {}",
205                     source_text, n, substring, i
206                 );
207             });
208             let lo = hi + offset;
209             hi = lo + substring.len();
210             if i == n {
211                 let span = Span::with_root_ctxt(
212                     BytePos(lo as u32 + file.start_pos.0),
213                     BytePos(hi as u32 + file.start_pos.0),
214                 );
215                 assert_eq!(&self.span_to_snippet(span).unwrap()[..], substring);
216                 return span;
217             }
218             i += 1;
219         }
220     }
221 }