blob: b1392a1d75d768f0caa121d87cfbc6534f617c11 [file] [log] [blame]
Matthew Maurer597ccd52023-06-12 16:37:41 +00001use annotate_snippets::display_list::*;
2use annotate_snippets::snippet::{self, Snippet};
3
4#[test]
5fn test_source_empty() {
6 let dl = DisplayList::from(vec![DisplayLine::Source {
7 lineno: None,
8 inline_marks: vec![],
9 line: DisplaySourceLine::Empty,
10 }]);
11
12 assert_eq!(dl.to_string(), " |");
13}
14
15#[test]
16fn test_source_content() {
17 let dl = DisplayList::from(vec![
18 DisplayLine::Source {
19 lineno: Some(56),
20 inline_marks: vec![],
21 line: DisplaySourceLine::Content {
22 text: "This is an example",
23 range: (0, 19),
24 },
25 },
26 DisplayLine::Source {
27 lineno: Some(57),
28 inline_marks: vec![],
29 line: DisplaySourceLine::Content {
30 text: "of content lines",
31 range: (0, 19),
32 },
33 },
34 ]);
35
36 assert_eq!(
37 dl.to_string(),
38 "56 | This is an example\n57 | of content lines"
39 );
40}
41
42#[test]
43fn test_source_annotation_standalone_singleline() {
44 let dl = DisplayList::from(vec![DisplayLine::Source {
45 lineno: None,
46 inline_marks: vec![],
47 line: DisplaySourceLine::Annotation {
48 range: (0, 5),
49 annotation: Annotation {
50 annotation_type: DisplayAnnotationType::None,
51 id: None,
52 label: vec![DisplayTextFragment {
53 content: "Example string",
54 style: DisplayTextStyle::Regular,
55 }],
56 },
57 annotation_type: DisplayAnnotationType::Error,
58 annotation_part: DisplayAnnotationPart::Standalone,
59 },
60 }]);
61
62 assert_eq!(dl.to_string(), " | ^^^^^ Example string");
63}
64
65#[test]
66fn test_source_annotation_standalone_multiline() {
67 let dl = DisplayList::from(vec![
68 DisplayLine::Source {
69 lineno: None,
70 inline_marks: vec![],
71 line: DisplaySourceLine::Annotation {
72 range: (0, 5),
73 annotation: Annotation {
74 annotation_type: DisplayAnnotationType::Help,
75 id: None,
76 label: vec![DisplayTextFragment {
77 content: "Example string",
78 style: DisplayTextStyle::Regular,
79 }],
80 },
81 annotation_type: DisplayAnnotationType::Warning,
82 annotation_part: DisplayAnnotationPart::Standalone,
83 },
84 },
85 DisplayLine::Source {
86 lineno: None,
87 inline_marks: vec![],
88 line: DisplaySourceLine::Annotation {
89 range: (0, 5),
90 annotation: Annotation {
91 annotation_type: DisplayAnnotationType::Help,
92 id: None,
93 label: vec![DisplayTextFragment {
94 content: "Second line",
95 style: DisplayTextStyle::Regular,
96 }],
97 },
98 annotation_type: DisplayAnnotationType::Warning,
99 annotation_part: DisplayAnnotationPart::LabelContinuation,
100 },
101 },
102 ]);
103
104 assert_eq!(
105 dl.to_string(),
106 " | ----- help: Example string\n | Second line"
107 );
108}
109
110#[test]
111fn test_source_annotation_standalone_multi_annotation() {
112 let dl = DisplayList::from(vec![
113 DisplayLine::Source {
114 lineno: None,
115 inline_marks: vec![],
116 line: DisplaySourceLine::Annotation {
117 range: (0, 5),
118 annotation: Annotation {
119 annotation_type: DisplayAnnotationType::Info,
120 id: None,
121 label: vec![DisplayTextFragment {
122 content: "Example string",
123 style: DisplayTextStyle::Regular,
124 }],
125 },
126 annotation_type: DisplayAnnotationType::Note,
127 annotation_part: DisplayAnnotationPart::Standalone,
128 },
129 },
130 DisplayLine::Source {
131 lineno: None,
132 inline_marks: vec![],
133 line: DisplaySourceLine::Annotation {
134 range: (0, 5),
135 annotation: Annotation {
136 annotation_type: DisplayAnnotationType::Info,
137 id: None,
138 label: vec![DisplayTextFragment {
139 content: "Second line",
140 style: DisplayTextStyle::Regular,
141 }],
142 },
143 annotation_type: DisplayAnnotationType::Note,
144 annotation_part: DisplayAnnotationPart::LabelContinuation,
145 },
146 },
147 DisplayLine::Source {
148 lineno: None,
149 inline_marks: vec![],
150 line: DisplaySourceLine::Annotation {
151 range: (0, 5),
152 annotation: Annotation {
153 annotation_type: DisplayAnnotationType::Warning,
154 id: None,
155 label: vec![DisplayTextFragment {
156 content: "This is a note",
157 style: DisplayTextStyle::Regular,
158 }],
159 },
160 annotation_type: DisplayAnnotationType::Note,
161 annotation_part: DisplayAnnotationPart::Consequitive,
162 },
163 },
164 DisplayLine::Source {
165 lineno: None,
166 inline_marks: vec![],
167 line: DisplaySourceLine::Annotation {
168 range: (0, 5),
169 annotation: Annotation {
170 annotation_type: DisplayAnnotationType::Warning,
171 id: None,
172 label: vec![DisplayTextFragment {
173 content: "Second line of the warning",
174 style: DisplayTextStyle::Regular,
175 }],
176 },
177 annotation_type: DisplayAnnotationType::Note,
178 annotation_part: DisplayAnnotationPart::LabelContinuation,
179 },
180 },
181 DisplayLine::Source {
182 lineno: None,
183 inline_marks: vec![],
184 line: DisplaySourceLine::Annotation {
185 range: (0, 5),
186 annotation: Annotation {
187 annotation_type: DisplayAnnotationType::Info,
188 id: None,
189 label: vec![DisplayTextFragment {
190 content: "This is an info",
191 style: DisplayTextStyle::Regular,
192 }],
193 },
194 annotation_type: DisplayAnnotationType::Info,
195 annotation_part: DisplayAnnotationPart::Standalone,
196 },
197 },
198 DisplayLine::Source {
199 lineno: None,
200 inline_marks: vec![],
201 line: DisplaySourceLine::Annotation {
202 range: (0, 5),
203 annotation: Annotation {
204 annotation_type: DisplayAnnotationType::Help,
205 id: None,
206 label: vec![DisplayTextFragment {
207 content: "This is help",
208 style: DisplayTextStyle::Regular,
209 }],
210 },
211 annotation_type: DisplayAnnotationType::Help,
212 annotation_part: DisplayAnnotationPart::Standalone,
213 },
214 },
215 DisplayLine::Source {
216 lineno: None,
217 inline_marks: vec![],
218 line: DisplaySourceLine::Annotation {
219 range: (0, 0),
220 annotation: Annotation {
221 annotation_type: DisplayAnnotationType::None,
222 id: None,
223 label: vec![DisplayTextFragment {
224 content: "This is an annotation of type none",
225 style: DisplayTextStyle::Regular,
226 }],
227 },
228 annotation_type: DisplayAnnotationType::None,
229 annotation_part: DisplayAnnotationPart::Standalone,
230 },
231 },
232 ]);
233
234 assert_eq!(dl.to_string(), " | ----- info: Example string\n | Second line\n | warning: This is a note\n | Second line of the warning\n | ----- info: This is an info\n | ----- help: This is help\n | This is an annotation of type none");
235}
236
237#[test]
238fn test_fold_line() {
239 let dl = DisplayList::from(vec![
240 DisplayLine::Source {
241 lineno: Some(5),
242 inline_marks: vec![],
243 line: DisplaySourceLine::Content {
244 text: "This is line 5",
245 range: (0, 19),
246 },
247 },
248 DisplayLine::Fold {
249 inline_marks: vec![],
250 },
251 DisplayLine::Source {
252 lineno: Some(10021),
253 inline_marks: vec![],
254 line: DisplaySourceLine::Content {
255 text: "... and now we're at line 10021",
256 range: (0, 19),
257 },
258 },
259 ]);
260
261 assert_eq!(
262 dl.to_string(),
263 " 5 | This is line 5\n...\n10021 | ... and now we're at line 10021"
264 );
265}
266
267#[test]
268fn test_raw_origin_initial_nopos() {
269 let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Origin {
270 path: "src/test.rs",
271 pos: None,
272 header_type: DisplayHeaderType::Initial,
273 })]);
274
275 assert_eq!(dl.to_string(), "--> src/test.rs");
276}
277
278#[test]
279fn test_raw_origin_initial_pos() {
280 let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Origin {
281 path: "src/test.rs",
282 pos: Some((23, 15)),
283 header_type: DisplayHeaderType::Initial,
284 })]);
285
286 assert_eq!(dl.to_string(), "--> src/test.rs:23:15");
287}
288
289#[test]
290fn test_raw_origin_continuation() {
291 let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Origin {
292 path: "src/test.rs",
293 pos: Some((23, 15)),
294 header_type: DisplayHeaderType::Continuation,
295 })]);
296
297 assert_eq!(dl.to_string(), "::: src/test.rs:23:15");
298}
299
300#[test]
301fn test_raw_annotation_unaligned() {
302 let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Annotation {
303 annotation: Annotation {
304 annotation_type: DisplayAnnotationType::Error,
305 id: Some("E0001"),
306 label: vec![DisplayTextFragment {
307 content: "This is an error",
308 style: DisplayTextStyle::Regular,
309 }],
310 },
311 source_aligned: false,
312 continuation: false,
313 })]);
314
315 assert_eq!(dl.to_string(), "error[E0001]: This is an error");
316}
317
318#[test]
319fn test_raw_annotation_unaligned_multiline() {
320 let dl = DisplayList::from(vec![
321 DisplayLine::Raw(DisplayRawLine::Annotation {
322 annotation: Annotation {
323 annotation_type: DisplayAnnotationType::Warning,
324 id: Some("E0001"),
325 label: vec![DisplayTextFragment {
326 content: "This is an error",
327 style: DisplayTextStyle::Regular,
328 }],
329 },
330 source_aligned: false,
331 continuation: false,
332 }),
333 DisplayLine::Raw(DisplayRawLine::Annotation {
334 annotation: Annotation {
335 annotation_type: DisplayAnnotationType::Warning,
336 id: Some("E0001"),
337 label: vec![DisplayTextFragment {
338 content: "Second line of the error",
339 style: DisplayTextStyle::Regular,
340 }],
341 },
342 source_aligned: false,
343 continuation: true,
344 }),
345 ]);
346
347 assert_eq!(
348 dl.to_string(),
349 "warning[E0001]: This is an error\n Second line of the error"
350 );
351}
352
353#[test]
354fn test_raw_annotation_aligned() {
355 let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Annotation {
356 annotation: Annotation {
357 annotation_type: DisplayAnnotationType::Error,
358 id: Some("E0001"),
359 label: vec![DisplayTextFragment {
360 content: "This is an error",
361 style: DisplayTextStyle::Regular,
362 }],
363 },
364 source_aligned: true,
365 continuation: false,
366 })]);
367
368 assert_eq!(dl.to_string(), " = error[E0001]: This is an error");
369}
370
371#[test]
372fn test_raw_annotation_aligned_multiline() {
373 let dl = DisplayList::from(vec![
374 DisplayLine::Raw(DisplayRawLine::Annotation {
375 annotation: Annotation {
376 annotation_type: DisplayAnnotationType::Warning,
377 id: Some("E0001"),
378 label: vec![DisplayTextFragment {
379 content: "This is an error",
380 style: DisplayTextStyle::Regular,
381 }],
382 },
383 source_aligned: true,
384 continuation: false,
385 }),
386 DisplayLine::Raw(DisplayRawLine::Annotation {
387 annotation: Annotation {
388 annotation_type: DisplayAnnotationType::Warning,
389 id: Some("E0001"),
390 label: vec![DisplayTextFragment {
391 content: "Second line of the error",
392 style: DisplayTextStyle::Regular,
393 }],
394 },
395 source_aligned: true,
396 continuation: true,
397 }),
398 ]);
399
400 assert_eq!(
401 dl.to_string(),
402 " = warning[E0001]: This is an error\n Second line of the error"
403 );
404}
405
406#[test]
407fn test_different_annotation_types() {
408 let dl = DisplayList::from(vec![
409 DisplayLine::Raw(DisplayRawLine::Annotation {
410 annotation: Annotation {
411 annotation_type: DisplayAnnotationType::Note,
412 id: None,
413 label: vec![DisplayTextFragment {
414 content: "This is a note",
415 style: DisplayTextStyle::Regular,
416 }],
417 },
418 source_aligned: false,
419 continuation: false,
420 }),
421 DisplayLine::Raw(DisplayRawLine::Annotation {
422 annotation: Annotation {
423 annotation_type: DisplayAnnotationType::None,
424 id: None,
425 label: vec![DisplayTextFragment {
426 content: "This is just a string",
427 style: DisplayTextStyle::Regular,
428 }],
429 },
430 source_aligned: false,
431 continuation: false,
432 }),
433 DisplayLine::Raw(DisplayRawLine::Annotation {
434 annotation: Annotation {
435 annotation_type: DisplayAnnotationType::None,
436 id: None,
437 label: vec![DisplayTextFragment {
438 content: "Second line of none type annotation",
439 style: DisplayTextStyle::Regular,
440 }],
441 },
442 source_aligned: false,
443 continuation: true,
444 }),
445 ]);
446
447 assert_eq!(
448 dl.to_string(),
449 "note: This is a note\nThis is just a string\n Second line of none type annotation",
450 );
451}
452
453#[test]
454fn test_inline_marks_empty_line() {
455 let dl = DisplayList::from(vec![DisplayLine::Source {
456 lineno: None,
457 inline_marks: vec![DisplayMark {
458 mark_type: DisplayMarkType::AnnotationThrough,
459 annotation_type: DisplayAnnotationType::Error,
460 }],
461 line: DisplaySourceLine::Empty,
462 }]);
463
464 assert_eq!(dl.to_string(), " | |",);
465}
466
467#[test]
468fn test_anon_lines() {
469 let mut dl = DisplayList::from(vec![
470 DisplayLine::Source {
471 lineno: Some(56),
472 inline_marks: vec![],
473 line: DisplaySourceLine::Content {
474 text: "This is an example",
475 range: (0, 19),
476 },
477 },
478 DisplayLine::Source {
479 lineno: Some(57),
480 inline_marks: vec![],
481 line: DisplaySourceLine::Content {
482 text: "of content lines",
483 range: (0, 19),
484 },
485 },
486 DisplayLine::Source {
487 lineno: None,
488 inline_marks: vec![],
489 line: DisplaySourceLine::Empty,
490 },
491 DisplayLine::Source {
492 lineno: None,
493 inline_marks: vec![],
494 line: DisplaySourceLine::Content {
495 text: "abc",
496 range: (0, 19),
497 },
498 },
499 ]);
500
501 dl.anonymized_line_numbers = true;
502 assert_eq!(
503 dl.to_string(),
504 "LL | This is an example\nLL | of content lines\n |\n | abc"
505 );
506}
507
508#[test]
509fn test_raw_origin_initial_pos_anon_lines() {
510 let mut dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Origin {
511 path: "src/test.rs",
512 pos: Some((23, 15)),
513 header_type: DisplayHeaderType::Initial,
514 })]);
515
516 // Using anonymized_line_numbers should not affect the inital position
517 dl.anonymized_line_numbers = true;
518 assert_eq!(dl.to_string(), "--> src/test.rs:23:15");
519}
520
521#[test]
522fn test_i_29() {
523 let snippets = Snippet {
524 title: Some(snippet::Annotation {
525 id: None,
526 label: Some("oops"),
527 annotation_type: snippet::AnnotationType::Error,
528 }),
529 footer: vec![],
530 slices: vec![snippet::Slice {
531 source: "First line\r\nSecond oops line",
532 line_start: 1,
533 origin: Some("<current file>"),
534 annotations: vec![snippet::SourceAnnotation {
535 range: (19, 23),
536 label: "oops",
537 annotation_type: snippet::AnnotationType::Error,
538 }],
539 fold: true,
540 }],
541 opt: Default::default(),
542 };
543 let expected = r#"error: oops
544 --> <current file>:2:8
545 |
5461 | First line
5472 | Second oops line
548 | ^^^^ oops
549 |"#;
550
551 assert_eq!(DisplayList::from(snippets).to_string(), expected);
552}
553
554#[test]
555fn test_point_to_double_width_characters() {
556 let snippets = Snippet {
557 slices: vec![snippet::Slice {
558 source: "こんにちは、世界",
559 line_start: 1,
560 origin: Some("<current file>"),
561 annotations: vec![snippet::SourceAnnotation {
562 range: (6, 8),
563 label: "world",
564 annotation_type: snippet::AnnotationType::Error,
565 }],
566 fold: false,
567 }],
568 title: None,
569 footer: vec![],
570 opt: Default::default(),
571 };
572
573 let expected = r#" --> <current file>:1:7
574 |
5751 | こんにちは、世界
576 | ^^^^ world
577 |"#;
578
579 assert_eq!(DisplayList::from(snippets).to_string(), expected);
580}
581
582#[test]
583fn test_point_to_double_width_characters_across_lines() {
584 let snippets = Snippet {
585 slices: vec![snippet::Slice {
586 source: "おはよう\nございます",
587 line_start: 1,
588 origin: Some("<current file>"),
589 annotations: vec![snippet::SourceAnnotation {
590 range: (2, 8),
591 label: "Good morning",
592 annotation_type: snippet::AnnotationType::Error,
593 }],
594 fold: false,
595 }],
596 title: None,
597 footer: vec![],
598 opt: Default::default(),
599 };
600
601 let expected = r#" --> <current file>:1:3
602 |
6031 | おはよう
604 | _____^
6052 | | ございます
606 | |______^ Good morning
607 |"#;
608
609 assert_eq!(DisplayList::from(snippets).to_string(), expected);
610}
611
612#[test]
613fn test_point_to_double_width_characters_multiple() {
614 let snippets = Snippet {
615 slices: vec![snippet::Slice {
616 source: "お寿司\n食べたい🍣",
617 line_start: 1,
618 origin: Some("<current file>"),
619 annotations: vec![
620 snippet::SourceAnnotation {
621 range: (0, 3),
622 label: "Sushi1",
623 annotation_type: snippet::AnnotationType::Error,
624 },
625 snippet::SourceAnnotation {
626 range: (6, 8),
627 label: "Sushi2",
628 annotation_type: snippet::AnnotationType::Note,
629 },
630 ],
631 fold: false,
632 }],
633 title: None,
634 footer: vec![],
635 opt: Default::default(),
636 };
637
638 let expected = r#" --> <current file>:1:1
639 |
6401 | お寿司
641 | ^^^^^^ Sushi1
6422 | 食べたい🍣
643 | ---- note: Sushi2
644 |"#;
645
646 assert_eq!(DisplayList::from(snippets).to_string(), expected);
647}
648
649#[test]
650fn test_point_to_double_width_characters_mixed() {
651 let snippets = Snippet {
652 slices: vec![snippet::Slice {
653 source: "こんにちは、新しいWorld!",
654 line_start: 1,
655 origin: Some("<current file>"),
656 annotations: vec![snippet::SourceAnnotation {
657 range: (6, 14),
658 label: "New world",
659 annotation_type: snippet::AnnotationType::Error,
660 }],
661 fold: false,
662 }],
663 title: None,
664 footer: vec![],
665 opt: Default::default(),
666 };
667
668 let expected = r#" --> <current file>:1:7
669 |
6701 | こんにちは、新しいWorld
671 | ^^^^^^^^^^^ New world
672 |"#;
673
674 assert_eq!(DisplayList::from(snippets).to_string(), expected);
675}