| use annotate_snippets::display_list::*; |
| use annotate_snippets::snippet::{self, Snippet}; |
| |
| #[test] |
| fn test_source_empty() { |
| let dl = DisplayList::from(vec![DisplayLine::Source { |
| lineno: None, |
| inline_marks: vec![], |
| line: DisplaySourceLine::Empty, |
| }]); |
| |
| assert_eq!(dl.to_string(), " |"); |
| } |
| |
| #[test] |
| fn test_source_content() { |
| let dl = DisplayList::from(vec![ |
| DisplayLine::Source { |
| lineno: Some(56), |
| inline_marks: vec![], |
| line: DisplaySourceLine::Content { |
| text: "This is an example", |
| range: (0, 19), |
| }, |
| }, |
| DisplayLine::Source { |
| lineno: Some(57), |
| inline_marks: vec![], |
| line: DisplaySourceLine::Content { |
| text: "of content lines", |
| range: (0, 19), |
| }, |
| }, |
| ]); |
| |
| assert_eq!( |
| dl.to_string(), |
| "56 | This is an example\n57 | of content lines" |
| ); |
| } |
| |
| #[test] |
| fn test_source_annotation_standalone_singleline() { |
| let dl = DisplayList::from(vec![DisplayLine::Source { |
| lineno: None, |
| inline_marks: vec![], |
| line: DisplaySourceLine::Annotation { |
| range: (0, 5), |
| annotation: Annotation { |
| annotation_type: DisplayAnnotationType::None, |
| id: None, |
| label: vec![DisplayTextFragment { |
| content: "Example string", |
| style: DisplayTextStyle::Regular, |
| }], |
| }, |
| annotation_type: DisplayAnnotationType::Error, |
| annotation_part: DisplayAnnotationPart::Standalone, |
| }, |
| }]); |
| |
| assert_eq!(dl.to_string(), " | ^^^^^ Example string"); |
| } |
| |
| #[test] |
| fn test_source_annotation_standalone_multiline() { |
| let dl = DisplayList::from(vec![ |
| DisplayLine::Source { |
| lineno: None, |
| inline_marks: vec![], |
| line: DisplaySourceLine::Annotation { |
| range: (0, 5), |
| annotation: Annotation { |
| annotation_type: DisplayAnnotationType::Help, |
| id: None, |
| label: vec![DisplayTextFragment { |
| content: "Example string", |
| style: DisplayTextStyle::Regular, |
| }], |
| }, |
| annotation_type: DisplayAnnotationType::Warning, |
| annotation_part: DisplayAnnotationPart::Standalone, |
| }, |
| }, |
| DisplayLine::Source { |
| lineno: None, |
| inline_marks: vec![], |
| line: DisplaySourceLine::Annotation { |
| range: (0, 5), |
| annotation: Annotation { |
| annotation_type: DisplayAnnotationType::Help, |
| id: None, |
| label: vec![DisplayTextFragment { |
| content: "Second line", |
| style: DisplayTextStyle::Regular, |
| }], |
| }, |
| annotation_type: DisplayAnnotationType::Warning, |
| annotation_part: DisplayAnnotationPart::LabelContinuation, |
| }, |
| }, |
| ]); |
| |
| assert_eq!( |
| dl.to_string(), |
| " | ----- help: Example string\n | Second line" |
| ); |
| } |
| |
| #[test] |
| fn test_source_annotation_standalone_multi_annotation() { |
| let dl = DisplayList::from(vec![ |
| DisplayLine::Source { |
| lineno: None, |
| inline_marks: vec![], |
| line: DisplaySourceLine::Annotation { |
| range: (0, 5), |
| annotation: Annotation { |
| annotation_type: DisplayAnnotationType::Info, |
| id: None, |
| label: vec![DisplayTextFragment { |
| content: "Example string", |
| style: DisplayTextStyle::Regular, |
| }], |
| }, |
| annotation_type: DisplayAnnotationType::Note, |
| annotation_part: DisplayAnnotationPart::Standalone, |
| }, |
| }, |
| DisplayLine::Source { |
| lineno: None, |
| inline_marks: vec![], |
| line: DisplaySourceLine::Annotation { |
| range: (0, 5), |
| annotation: Annotation { |
| annotation_type: DisplayAnnotationType::Info, |
| id: None, |
| label: vec![DisplayTextFragment { |
| content: "Second line", |
| style: DisplayTextStyle::Regular, |
| }], |
| }, |
| annotation_type: DisplayAnnotationType::Note, |
| annotation_part: DisplayAnnotationPart::LabelContinuation, |
| }, |
| }, |
| DisplayLine::Source { |
| lineno: None, |
| inline_marks: vec![], |
| line: DisplaySourceLine::Annotation { |
| range: (0, 5), |
| annotation: Annotation { |
| annotation_type: DisplayAnnotationType::Warning, |
| id: None, |
| label: vec![DisplayTextFragment { |
| content: "This is a note", |
| style: DisplayTextStyle::Regular, |
| }], |
| }, |
| annotation_type: DisplayAnnotationType::Note, |
| annotation_part: DisplayAnnotationPart::Consequitive, |
| }, |
| }, |
| DisplayLine::Source { |
| lineno: None, |
| inline_marks: vec![], |
| line: DisplaySourceLine::Annotation { |
| range: (0, 5), |
| annotation: Annotation { |
| annotation_type: DisplayAnnotationType::Warning, |
| id: None, |
| label: vec![DisplayTextFragment { |
| content: "Second line of the warning", |
| style: DisplayTextStyle::Regular, |
| }], |
| }, |
| annotation_type: DisplayAnnotationType::Note, |
| annotation_part: DisplayAnnotationPart::LabelContinuation, |
| }, |
| }, |
| DisplayLine::Source { |
| lineno: None, |
| inline_marks: vec![], |
| line: DisplaySourceLine::Annotation { |
| range: (0, 5), |
| annotation: Annotation { |
| annotation_type: DisplayAnnotationType::Info, |
| id: None, |
| label: vec![DisplayTextFragment { |
| content: "This is an info", |
| style: DisplayTextStyle::Regular, |
| }], |
| }, |
| annotation_type: DisplayAnnotationType::Info, |
| annotation_part: DisplayAnnotationPart::Standalone, |
| }, |
| }, |
| DisplayLine::Source { |
| lineno: None, |
| inline_marks: vec![], |
| line: DisplaySourceLine::Annotation { |
| range: (0, 5), |
| annotation: Annotation { |
| annotation_type: DisplayAnnotationType::Help, |
| id: None, |
| label: vec![DisplayTextFragment { |
| content: "This is help", |
| style: DisplayTextStyle::Regular, |
| }], |
| }, |
| annotation_type: DisplayAnnotationType::Help, |
| annotation_part: DisplayAnnotationPart::Standalone, |
| }, |
| }, |
| DisplayLine::Source { |
| lineno: None, |
| inline_marks: vec![], |
| line: DisplaySourceLine::Annotation { |
| range: (0, 0), |
| annotation: Annotation { |
| annotation_type: DisplayAnnotationType::None, |
| id: None, |
| label: vec![DisplayTextFragment { |
| content: "This is an annotation of type none", |
| style: DisplayTextStyle::Regular, |
| }], |
| }, |
| annotation_type: DisplayAnnotationType::None, |
| annotation_part: DisplayAnnotationPart::Standalone, |
| }, |
| }, |
| ]); |
| |
| 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"); |
| } |
| |
| #[test] |
| fn test_fold_line() { |
| let dl = DisplayList::from(vec![ |
| DisplayLine::Source { |
| lineno: Some(5), |
| inline_marks: vec![], |
| line: DisplaySourceLine::Content { |
| text: "This is line 5", |
| range: (0, 19), |
| }, |
| }, |
| DisplayLine::Fold { |
| inline_marks: vec![], |
| }, |
| DisplayLine::Source { |
| lineno: Some(10021), |
| inline_marks: vec![], |
| line: DisplaySourceLine::Content { |
| text: "... and now we're at line 10021", |
| range: (0, 19), |
| }, |
| }, |
| ]); |
| |
| assert_eq!( |
| dl.to_string(), |
| " 5 | This is line 5\n...\n10021 | ... and now we're at line 10021" |
| ); |
| } |
| |
| #[test] |
| fn test_raw_origin_initial_nopos() { |
| let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Origin { |
| path: "src/test.rs", |
| pos: None, |
| header_type: DisplayHeaderType::Initial, |
| })]); |
| |
| assert_eq!(dl.to_string(), "--> src/test.rs"); |
| } |
| |
| #[test] |
| fn test_raw_origin_initial_pos() { |
| let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Origin { |
| path: "src/test.rs", |
| pos: Some((23, 15)), |
| header_type: DisplayHeaderType::Initial, |
| })]); |
| |
| assert_eq!(dl.to_string(), "--> src/test.rs:23:15"); |
| } |
| |
| #[test] |
| fn test_raw_origin_continuation() { |
| let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Origin { |
| path: "src/test.rs", |
| pos: Some((23, 15)), |
| header_type: DisplayHeaderType::Continuation, |
| })]); |
| |
| assert_eq!(dl.to_string(), "::: src/test.rs:23:15"); |
| } |
| |
| #[test] |
| fn test_raw_annotation_unaligned() { |
| let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Annotation { |
| annotation: Annotation { |
| annotation_type: DisplayAnnotationType::Error, |
| id: Some("E0001"), |
| label: vec![DisplayTextFragment { |
| content: "This is an error", |
| style: DisplayTextStyle::Regular, |
| }], |
| }, |
| source_aligned: false, |
| continuation: false, |
| })]); |
| |
| assert_eq!(dl.to_string(), "error[E0001]: This is an error"); |
| } |
| |
| #[test] |
| fn test_raw_annotation_unaligned_multiline() { |
| let dl = DisplayList::from(vec![ |
| DisplayLine::Raw(DisplayRawLine::Annotation { |
| annotation: Annotation { |
| annotation_type: DisplayAnnotationType::Warning, |
| id: Some("E0001"), |
| label: vec![DisplayTextFragment { |
| content: "This is an error", |
| style: DisplayTextStyle::Regular, |
| }], |
| }, |
| source_aligned: false, |
| continuation: false, |
| }), |
| DisplayLine::Raw(DisplayRawLine::Annotation { |
| annotation: Annotation { |
| annotation_type: DisplayAnnotationType::Warning, |
| id: Some("E0001"), |
| label: vec![DisplayTextFragment { |
| content: "Second line of the error", |
| style: DisplayTextStyle::Regular, |
| }], |
| }, |
| source_aligned: false, |
| continuation: true, |
| }), |
| ]); |
| |
| assert_eq!( |
| dl.to_string(), |
| "warning[E0001]: This is an error\n Second line of the error" |
| ); |
| } |
| |
| #[test] |
| fn test_raw_annotation_aligned() { |
| let dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Annotation { |
| annotation: Annotation { |
| annotation_type: DisplayAnnotationType::Error, |
| id: Some("E0001"), |
| label: vec![DisplayTextFragment { |
| content: "This is an error", |
| style: DisplayTextStyle::Regular, |
| }], |
| }, |
| source_aligned: true, |
| continuation: false, |
| })]); |
| |
| assert_eq!(dl.to_string(), " = error[E0001]: This is an error"); |
| } |
| |
| #[test] |
| fn test_raw_annotation_aligned_multiline() { |
| let dl = DisplayList::from(vec![ |
| DisplayLine::Raw(DisplayRawLine::Annotation { |
| annotation: Annotation { |
| annotation_type: DisplayAnnotationType::Warning, |
| id: Some("E0001"), |
| label: vec![DisplayTextFragment { |
| content: "This is an error", |
| style: DisplayTextStyle::Regular, |
| }], |
| }, |
| source_aligned: true, |
| continuation: false, |
| }), |
| DisplayLine::Raw(DisplayRawLine::Annotation { |
| annotation: Annotation { |
| annotation_type: DisplayAnnotationType::Warning, |
| id: Some("E0001"), |
| label: vec![DisplayTextFragment { |
| content: "Second line of the error", |
| style: DisplayTextStyle::Regular, |
| }], |
| }, |
| source_aligned: true, |
| continuation: true, |
| }), |
| ]); |
| |
| assert_eq!( |
| dl.to_string(), |
| " = warning[E0001]: This is an error\n Second line of the error" |
| ); |
| } |
| |
| #[test] |
| fn test_different_annotation_types() { |
| let dl = DisplayList::from(vec![ |
| DisplayLine::Raw(DisplayRawLine::Annotation { |
| annotation: Annotation { |
| annotation_type: DisplayAnnotationType::Note, |
| id: None, |
| label: vec![DisplayTextFragment { |
| content: "This is a note", |
| style: DisplayTextStyle::Regular, |
| }], |
| }, |
| source_aligned: false, |
| continuation: false, |
| }), |
| DisplayLine::Raw(DisplayRawLine::Annotation { |
| annotation: Annotation { |
| annotation_type: DisplayAnnotationType::None, |
| id: None, |
| label: vec![DisplayTextFragment { |
| content: "This is just a string", |
| style: DisplayTextStyle::Regular, |
| }], |
| }, |
| source_aligned: false, |
| continuation: false, |
| }), |
| DisplayLine::Raw(DisplayRawLine::Annotation { |
| annotation: Annotation { |
| annotation_type: DisplayAnnotationType::None, |
| id: None, |
| label: vec![DisplayTextFragment { |
| content: "Second line of none type annotation", |
| style: DisplayTextStyle::Regular, |
| }], |
| }, |
| source_aligned: false, |
| continuation: true, |
| }), |
| ]); |
| |
| assert_eq!( |
| dl.to_string(), |
| "note: This is a note\nThis is just a string\n Second line of none type annotation", |
| ); |
| } |
| |
| #[test] |
| fn test_inline_marks_empty_line() { |
| let dl = DisplayList::from(vec![DisplayLine::Source { |
| lineno: None, |
| inline_marks: vec![DisplayMark { |
| mark_type: DisplayMarkType::AnnotationThrough, |
| annotation_type: DisplayAnnotationType::Error, |
| }], |
| line: DisplaySourceLine::Empty, |
| }]); |
| |
| assert_eq!(dl.to_string(), " | |",); |
| } |
| |
| #[test] |
| fn test_anon_lines() { |
| let mut dl = DisplayList::from(vec![ |
| DisplayLine::Source { |
| lineno: Some(56), |
| inline_marks: vec![], |
| line: DisplaySourceLine::Content { |
| text: "This is an example", |
| range: (0, 19), |
| }, |
| }, |
| DisplayLine::Source { |
| lineno: Some(57), |
| inline_marks: vec![], |
| line: DisplaySourceLine::Content { |
| text: "of content lines", |
| range: (0, 19), |
| }, |
| }, |
| DisplayLine::Source { |
| lineno: None, |
| inline_marks: vec![], |
| line: DisplaySourceLine::Empty, |
| }, |
| DisplayLine::Source { |
| lineno: None, |
| inline_marks: vec![], |
| line: DisplaySourceLine::Content { |
| text: "abc", |
| range: (0, 19), |
| }, |
| }, |
| ]); |
| |
| dl.anonymized_line_numbers = true; |
| assert_eq!( |
| dl.to_string(), |
| "LL | This is an example\nLL | of content lines\n |\n | abc" |
| ); |
| } |
| |
| #[test] |
| fn test_raw_origin_initial_pos_anon_lines() { |
| let mut dl = DisplayList::from(vec![DisplayLine::Raw(DisplayRawLine::Origin { |
| path: "src/test.rs", |
| pos: Some((23, 15)), |
| header_type: DisplayHeaderType::Initial, |
| })]); |
| |
| // Using anonymized_line_numbers should not affect the inital position |
| dl.anonymized_line_numbers = true; |
| assert_eq!(dl.to_string(), "--> src/test.rs:23:15"); |
| } |
| |
| #[test] |
| fn test_i_29() { |
| let snippets = Snippet { |
| title: Some(snippet::Annotation { |
| id: None, |
| label: Some("oops"), |
| annotation_type: snippet::AnnotationType::Error, |
| }), |
| footer: vec![], |
| slices: vec![snippet::Slice { |
| source: "First line\r\nSecond oops line", |
| line_start: 1, |
| origin: Some("<current file>"), |
| annotations: vec![snippet::SourceAnnotation { |
| range: (19, 23), |
| label: "oops", |
| annotation_type: snippet::AnnotationType::Error, |
| }], |
| fold: true, |
| }], |
| opt: Default::default(), |
| }; |
| let expected = r#"error: oops |
| --> <current file>:2:8 |
| | |
| 1 | First line |
| 2 | Second oops line |
| | ^^^^ oops |
| |"#; |
| |
| assert_eq!(DisplayList::from(snippets).to_string(), expected); |
| } |
| |
| #[test] |
| fn test_point_to_double_width_characters() { |
| let snippets = Snippet { |
| slices: vec![snippet::Slice { |
| source: "こんにちは、世界", |
| line_start: 1, |
| origin: Some("<current file>"), |
| annotations: vec![snippet::SourceAnnotation { |
| range: (6, 8), |
| label: "world", |
| annotation_type: snippet::AnnotationType::Error, |
| }], |
| fold: false, |
| }], |
| title: None, |
| footer: vec![], |
| opt: Default::default(), |
| }; |
| |
| let expected = r#" --> <current file>:1:7 |
| | |
| 1 | こんにちは、世界 |
| | ^^^^ world |
| |"#; |
| |
| assert_eq!(DisplayList::from(snippets).to_string(), expected); |
| } |
| |
| #[test] |
| fn test_point_to_double_width_characters_across_lines() { |
| let snippets = Snippet { |
| slices: vec![snippet::Slice { |
| source: "おはよう\nございます", |
| line_start: 1, |
| origin: Some("<current file>"), |
| annotations: vec![snippet::SourceAnnotation { |
| range: (2, 8), |
| label: "Good morning", |
| annotation_type: snippet::AnnotationType::Error, |
| }], |
| fold: false, |
| }], |
| title: None, |
| footer: vec![], |
| opt: Default::default(), |
| }; |
| |
| let expected = r#" --> <current file>:1:3 |
| | |
| 1 | おはよう |
| | _____^ |
| 2 | | ございます |
| | |______^ Good morning |
| |"#; |
| |
| assert_eq!(DisplayList::from(snippets).to_string(), expected); |
| } |
| |
| #[test] |
| fn test_point_to_double_width_characters_multiple() { |
| let snippets = Snippet { |
| slices: vec![snippet::Slice { |
| source: "お寿司\n食べたい🍣", |
| line_start: 1, |
| origin: Some("<current file>"), |
| annotations: vec![ |
| snippet::SourceAnnotation { |
| range: (0, 3), |
| label: "Sushi1", |
| annotation_type: snippet::AnnotationType::Error, |
| }, |
| snippet::SourceAnnotation { |
| range: (6, 8), |
| label: "Sushi2", |
| annotation_type: snippet::AnnotationType::Note, |
| }, |
| ], |
| fold: false, |
| }], |
| title: None, |
| footer: vec![], |
| opt: Default::default(), |
| }; |
| |
| let expected = r#" --> <current file>:1:1 |
| | |
| 1 | お寿司 |
| | ^^^^^^ Sushi1 |
| 2 | 食べたい🍣 |
| | ---- note: Sushi2 |
| |"#; |
| |
| assert_eq!(DisplayList::from(snippets).to_string(), expected); |
| } |
| |
| #[test] |
| fn test_point_to_double_width_characters_mixed() { |
| let snippets = Snippet { |
| slices: vec![snippet::Slice { |
| source: "こんにちは、新しいWorld!", |
| line_start: 1, |
| origin: Some("<current file>"), |
| annotations: vec![snippet::SourceAnnotation { |
| range: (6, 14), |
| label: "New world", |
| annotation_type: snippet::AnnotationType::Error, |
| }], |
| fold: false, |
| }], |
| title: None, |
| footer: vec![], |
| opt: Default::default(), |
| }; |
| |
| let expected = r#" --> <current file>:1:7 |
| | |
| 1 | こんにちは、新しいWorld! |
| | ^^^^^^^^^^^ New world |
| |"#; |
| |
| assert_eq!(DisplayList::from(snippets).to_string(), expected); |
| } |