diff options
author | Aleksey Kladov <[email protected]> | 2020-07-14 13:57:33 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-07-14 13:58:10 +0100 |
commit | abeb003df47de4a1b7aa36a7c4d7987d8cf40ace (patch) | |
tree | c81e83fcb3c9abdae2a7b38020f6da9d5d05d833 /crates/test_utils | |
parent | 0b0865ab226d57c88e22b6b395d033f68f2c11af (diff) |
Allow multiline annotations
Diffstat (limited to 'crates/test_utils')
-rw-r--r-- | crates/test_utils/src/lib.rs | 67 |
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 | ||
195 | fn extract_line_annotations(mut line: &str) -> Vec<(TextRange, String)> { | 216 | enum LineAnnotation { |
217 | Annotation { range: TextRange, content: String }, | ||
218 | Continuation { offset: TextSize, content: String }, | ||
219 | } | ||
220 | |||
221 | fn 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: |