aboutsummaryrefslogtreecommitdiff
path: root/crates/test_utils/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-07-14 13:57:33 +0100
committerAleksey Kladov <[email protected]>2020-07-14 13:58:10 +0100
commitabeb003df47de4a1b7aa36a7c4d7987d8cf40ace (patch)
treec81e83fcb3c9abdae2a7b38020f6da9d5d05d833 /crates/test_utils/src
parent0b0865ab226d57c88e22b6b395d033f68f2c11af (diff)
Allow multiline annotations
Diffstat (limited to 'crates/test_utils/src')
-rw-r--r--crates/test_utils/src/lib.rs67
1 files changed, 56 insertions, 11 deletions
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs
index 4c89ed87b..ad586c882 100644
--- a/crates/test_utils/src/lib.rs
+++ b/crates/test_utils/src/lib.rs
@@ -179,24 +179,51 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> {
179 let mut res = Vec::new(); 179 let mut res = Vec::new();
180 let mut prev_line_start: Option<TextSize> = None; 180 let mut prev_line_start: Option<TextSize> = None;
181 let mut line_start: TextSize = 0.into(); 181 let mut line_start: TextSize = 0.into();
182 let mut prev_line_annotations: Vec<(TextSize, usize)> = Vec::new();
182 for line in lines_with_ends(text) { 183 for line in lines_with_ends(text) {
184 let mut this_line_annotations = Vec::new();
183 if let Some(idx) = line.find("//") { 185 if let Some(idx) = line.find("//") {
184 let offset = prev_line_start.unwrap() + TextSize::of(&line[..idx + "//".len()]); 186 let annotation_offset = TextSize::of(&line[..idx + "//".len()]);
185 for (line_range, text) in extract_line_annotations(&line[idx + "//".len()..]) { 187 for annotation in extract_line_annotations(&line[idx + "//".len()..]) {
186 res.push((line_range + offset, text)) 188 match annotation {
189 LineAnnotation::Annotation { mut range, content } => {
190 range += annotation_offset;
191 this_line_annotations.push((range.end(), res.len()));
192 res.push((range + prev_line_start.unwrap(), content))
193 }
194 LineAnnotation::Continuation { mut offset, content } => {
195 offset += annotation_offset;
196 let &(_, idx) = prev_line_annotations
197 .iter()
198 .find(|&&(off, _idx)| off == offset)
199 .unwrap();
200 res[idx].1.push('\n');
201 res[idx].1.push_str(&content);
202 res[idx].1.push('\n');
203 }
204 }
187 } 205 }
188 } 206 }
207
189 prev_line_start = Some(line_start); 208 prev_line_start = Some(line_start);
190 line_start += TextSize::of(line); 209 line_start += TextSize::of(line);
210
211 prev_line_annotations = this_line_annotations;
191 } 212 }
192 res 213 res
193} 214}
194 215
195fn extract_line_annotations(mut line: &str) -> Vec<(TextRange, String)> { 216enum LineAnnotation {
217 Annotation { range: TextRange, content: String },
218 Continuation { offset: TextSize, content: String },
219}
220
221fn extract_line_annotations(mut line: &str) -> Vec<LineAnnotation> {
196 let mut res = Vec::new(); 222 let mut res = Vec::new();
197 let mut offset: TextSize = 0.into(); 223 let mut offset: TextSize = 0.into();
224 let marker: fn(char) -> bool = if line.contains('^') { |c| c == '^' } else { |c| c == '|' };
198 loop { 225 loop {
199 match line.find('^') { 226 match line.find(marker) {
200 Some(idx) => { 227 Some(idx) => {
201 offset += TextSize::try_from(idx).unwrap(); 228 offset += TextSize::try_from(idx).unwrap();
202 line = &line[idx..]; 229 line = &line[idx..];
@@ -204,14 +231,28 @@ fn extract_line_annotations(mut line: &str) -> Vec<(TextRange, String)> {
204 None => break, 231 None => break,
205 }; 232 };
206 233
207 let len = line.chars().take_while(|&it| it == '^').count(); 234 let mut len = line.chars().take_while(|&it| it == '^').count();
208 assert!(len > 0); 235 let mut continuation = false;
236 if len == 0 {
237 assert!(line.starts_with('|'));
238 continuation = true;
239 len = 1;
240 }
209 let range = TextRange::at(offset, len.try_into().unwrap()); 241 let range = TextRange::at(offset, len.try_into().unwrap());
210 let next = line[len..].find('^').map_or(line.len(), |it| it + len); 242 let next = line[len..].find(marker).map_or(line.len(), |it| it + len);
211 res.push((range, line[len..][..next - len].trim().to_string())); 243 let content = line[len..][..next - len].trim().to_string();
244
245 let annotation = if continuation {
246 LineAnnotation::Continuation { offset: range.end(), content }
247 } else {
248 LineAnnotation::Annotation { range, content }
249 };
250 res.push(annotation);
251
212 line = &line[next..]; 252 line = &line[next..];
213 offset += TextSize::try_from(next).unwrap(); 253 offset += TextSize::try_from(next).unwrap();
214 } 254 }
255
215 res 256 res
216} 257}
217 258
@@ -223,14 +264,18 @@ fn main() {
223 let (x, y) = (9, 2); 264 let (x, y) = (9, 2);
224 //^ def ^ def 265 //^ def ^ def
225 zoo + 1 266 zoo + 1
226} //^^^ i32 267} //^^^ type:
268 // | i32
227 "#, 269 "#,
228 ); 270 );
229 let res = extract_annotations(&text) 271 let res = extract_annotations(&text)
230 .into_iter() 272 .into_iter()
231 .map(|(range, ann)| (&text[range], ann)) 273 .map(|(range, ann)| (&text[range], ann))
232 .collect::<Vec<_>>(); 274 .collect::<Vec<_>>();
233 assert_eq!(res, vec![("x", "def".into()), ("y", "def".into()), ("zoo", "i32".into()),]); 275 assert_eq!(
276 res,
277 vec![("x", "def".into()), ("y", "def".into()), ("zoo", "type:\ni32\n".into()),]
278 );
234} 279}
235 280
236// Comparison functionality borrowed from cargo: 281// Comparison functionality borrowed from cargo: