diff options
Diffstat (limited to 'crates/test_utils')
-rw-r--r-- | crates/test_utils/src/lib.rs | 58 |
1 files changed, 41 insertions, 17 deletions
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index bd017567c..b2fe25f82 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs | |||
@@ -190,10 +190,21 @@ pub fn add_cursor(text: &str, offset: TextSize) -> String { | |||
190 | res | 190 | res |
191 | } | 191 | } |
192 | 192 | ||
193 | /// Extracts `//^ some text` annotations | 193 | /// Extracts `//^^^ some text` annotations. |
194 | /// | ||
195 | /// A run of `^^^` can be arbitrary long and points to the corresponding range | ||
196 | /// in the line above. | ||
197 | /// | ||
198 | /// The `// ^file text` syntax can be used to attach `text` to the entirety of | ||
199 | /// the file. | ||
200 | /// | ||
201 | /// Multiline string values are supported: | ||
202 | /// | ||
203 | /// // ^^^ first line | ||
204 | /// // | second line | ||
194 | pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> { | 205 | pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> { |
195 | let mut res = Vec::new(); | 206 | let mut res = Vec::new(); |
196 | let mut prev_line_start: Option<TextSize> = None; | 207 | let mut prev_line_start: Option<TextSize> = Some(0.into()); |
197 | let mut line_start: TextSize = 0.into(); | 208 | let mut line_start: TextSize = 0.into(); |
198 | let mut prev_line_annotations: Vec<(TextSize, usize)> = Vec::new(); | 209 | let mut prev_line_annotations: Vec<(TextSize, usize)> = Vec::new(); |
199 | for line in text.split_inclusive('\n') { | 210 | for line in text.split_inclusive('\n') { |
@@ -202,10 +213,15 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> { | |||
202 | let annotation_offset = TextSize::of(&line[..idx + "//".len()]); | 213 | let annotation_offset = TextSize::of(&line[..idx + "//".len()]); |
203 | for annotation in extract_line_annotations(&line[idx + "//".len()..]) { | 214 | for annotation in extract_line_annotations(&line[idx + "//".len()..]) { |
204 | match annotation { | 215 | match annotation { |
205 | LineAnnotation::Annotation { mut range, content } => { | 216 | LineAnnotation::Annotation { mut range, content, file } => { |
206 | range += annotation_offset; | 217 | range += annotation_offset; |
207 | this_line_annotations.push((range.end(), res.len())); | 218 | this_line_annotations.push((range.end(), res.len())); |
208 | res.push((range + prev_line_start.unwrap(), content)) | 219 | let range = if file { |
220 | TextRange::up_to(TextSize::of(text)) | ||
221 | } else { | ||
222 | range + prev_line_start.unwrap() | ||
223 | }; | ||
224 | res.push((range, content)) | ||
209 | } | 225 | } |
210 | LineAnnotation::Continuation { mut offset, content } => { | 226 | LineAnnotation::Continuation { mut offset, content } => { |
211 | offset += annotation_offset; | 227 | offset += annotation_offset; |
@@ -226,11 +242,12 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> { | |||
226 | 242 | ||
227 | prev_line_annotations = this_line_annotations; | 243 | prev_line_annotations = this_line_annotations; |
228 | } | 244 | } |
245 | |||
229 | res | 246 | res |
230 | } | 247 | } |
231 | 248 | ||
232 | enum LineAnnotation { | 249 | enum LineAnnotation { |
233 | Annotation { range: TextRange, content: String }, | 250 | Annotation { range: TextRange, content: String, file: bool }, |
234 | Continuation { offset: TextSize, content: String }, | 251 | Continuation { offset: TextSize, content: String }, |
235 | } | 252 | } |
236 | 253 | ||
@@ -238,14 +255,9 @@ fn extract_line_annotations(mut line: &str) -> Vec<LineAnnotation> { | |||
238 | let mut res = Vec::new(); | 255 | let mut res = Vec::new(); |
239 | let mut offset: TextSize = 0.into(); | 256 | let mut offset: TextSize = 0.into(); |
240 | let marker: fn(char) -> bool = if line.contains('^') { |c| c == '^' } else { |c| c == '|' }; | 257 | let marker: fn(char) -> bool = if line.contains('^') { |c| c == '^' } else { |c| c == '|' }; |
241 | loop { | 258 | while let Some(idx) = line.find(marker) { |
242 | match line.find(marker) { | 259 | offset += TextSize::try_from(idx).unwrap(); |
243 | Some(idx) => { | 260 | line = &line[idx..]; |
244 | offset += TextSize::try_from(idx).unwrap(); | ||
245 | line = &line[idx..]; | ||
246 | } | ||
247 | None => break, | ||
248 | }; | ||
249 | 261 | ||
250 | let mut len = line.chars().take_while(|&it| it == '^').count(); | 262 | let mut len = line.chars().take_while(|&it| it == '^').count(); |
251 | let mut continuation = false; | 263 | let mut continuation = false; |
@@ -256,12 +268,20 @@ fn extract_line_annotations(mut line: &str) -> Vec<LineAnnotation> { | |||
256 | } | 268 | } |
257 | let range = TextRange::at(offset, len.try_into().unwrap()); | 269 | let range = TextRange::at(offset, len.try_into().unwrap()); |
258 | let next = line[len..].find(marker).map_or(line.len(), |it| it + len); | 270 | let next = line[len..].find(marker).map_or(line.len(), |it| it + len); |
259 | let content = line[len..][..next - len].trim().to_string(); | 271 | let mut content = &line[len..][..next - len]; |
272 | |||
273 | let mut file = false; | ||
274 | if !continuation && content.starts_with("file") { | ||
275 | file = true; | ||
276 | content = &content["file".len()..] | ||
277 | } | ||
278 | |||
279 | let content = content.trim().to_string(); | ||
260 | 280 | ||
261 | let annotation = if continuation { | 281 | let annotation = if continuation { |
262 | LineAnnotation::Continuation { offset: range.end(), content } | 282 | LineAnnotation::Continuation { offset: range.end(), content } |
263 | } else { | 283 | } else { |
264 | LineAnnotation::Annotation { range, content } | 284 | LineAnnotation::Annotation { range, content, file } |
265 | }; | 285 | }; |
266 | res.push(annotation); | 286 | res.push(annotation); |
267 | 287 | ||
@@ -282,16 +302,20 @@ fn main() { | |||
282 | zoo + 1 | 302 | zoo + 1 |
283 | } //^^^ type: | 303 | } //^^^ type: |
284 | // | i32 | 304 | // | i32 |
305 | |||
306 | // ^file | ||
285 | "#, | 307 | "#, |
286 | ); | 308 | ); |
287 | let res = extract_annotations(&text) | 309 | let res = extract_annotations(&text) |
288 | .into_iter() | 310 | .into_iter() |
289 | .map(|(range, ann)| (&text[range], ann)) | 311 | .map(|(range, ann)| (&text[range], ann)) |
290 | .collect::<Vec<_>>(); | 312 | .collect::<Vec<_>>(); |
313 | |||
291 | assert_eq!( | 314 | assert_eq!( |
292 | res, | 315 | res[..3], |
293 | vec![("x", "def".into()), ("y", "def".into()), ("zoo", "type:\ni32\n".into()),] | 316 | [("x", "def".into()), ("y", "def".into()), ("zoo", "type:\ni32\n".into())] |
294 | ); | 317 | ); |
318 | assert_eq!(res[3].0.len(), 115); | ||
295 | } | 319 | } |
296 | 320 | ||
297 | /// Returns `false` if slow tests should not run, otherwise returns `true` and | 321 | /// Returns `false` if slow tests should not run, otherwise returns `true` and |