diff --git a/src/renderer/display_list.rs b/src/renderer/display_list.rs index 89a779f..05c1910 100644 --- a/src/renderer/display_list.rs +++ b/src/renderer/display_list.rs @@ -1191,1039 +1191,3 @@ fn is_annotation_empty(annotation: &Annotation<'_>) -> bool { .iter() .all(|fragment| fragment.content.is_empty()) } - -#[cfg(test)] -mod tests { - use super::*; - - use snapbox::assert_eq; - use snapbox::str; - use snapbox::ToDebug as _; - - const STYLESHEET: Stylesheet = Stylesheet::plain(); - - fn from_display_lines(lines: Vec>) -> DisplayList<'_> { - DisplayList { - body: lines, - stylesheet: &STYLESHEET, - anonymized_line_numbers: false, - margin: None, - } - } - - #[test] - fn test_format_title() { - let input = snippet::Level::Error.title("This is a title").id("E0001"); - let output = str![[r#" - DisplayList { - body: [ - Raw( - Annotation { - annotation: Annotation { - annotation_type: Error, - id: Some( - "E0001", - ), - label: [ - DisplayTextFragment { - content: "This is a title", - style: Emphasis, - }, - ], - }, - source_aligned: false, - continuation: false, - }, - ), - ], - anonymized_line_numbers: false, - } - "#]]; - assert_eq( - output, - DisplayList::new(input, &STYLESHEET, false, None).to_debug(), - ); - } - - #[test] - fn test_format_slice() { - let line_1 = "This is line 1"; - let line_2 = "This is line 2"; - let source = [line_1, line_2].join("\n"); - let input = snippet::Level::Error - .title("") - .snippet(snippet::Snippet::source(&source).line_start(5402)); - let output = str![[r#" - DisplayList { - body: [ - Raw( - Annotation { - annotation: Annotation { - annotation_type: Error, - id: None, - label: [ - DisplayTextFragment { - content: "", - style: Emphasis, - }, - ], - }, - source_aligned: false, - continuation: false, - }, - ), - Source { - lineno: None, - inline_marks: [], - line: Empty, - }, - Source { - lineno: Some( - 5402, - ), - inline_marks: [], - line: Content { - text: "This is line 1", - range: ( - 0, - 14, - ), - }, - }, - Source { - lineno: Some( - 5403, - ), - inline_marks: [], - line: Content { - text: "This is line 2", - range: ( - 15, - 29, - ), - }, - }, - Source { - lineno: None, - inline_marks: [], - line: Empty, - }, - ], - anonymized_line_numbers: false, - } - "#]]; - assert_eq( - output, - DisplayList::new(input, &STYLESHEET, false, None).to_debug(), - ); - } - - #[test] - fn test_format_slices_continuation() { - let src_0 = "This is slice 1"; - let src_1 = "This is slice 2"; - let input = snippet::Level::Error - .title("") - .snippet( - snippet::Snippet::source(src_0) - .line_start(5402) - .origin("file1.rs"), - ) - .snippet( - snippet::Snippet::source(src_1) - .line_start(2) - .origin("file2.rs"), - ); - let output = str![[r#" - DisplayList { - body: [ - Raw( - Annotation { - annotation: Annotation { - annotation_type: Error, - id: None, - label: [ - DisplayTextFragment { - content: "", - style: Emphasis, - }, - ], - }, - source_aligned: false, - continuation: false, - }, - ), - Raw( - Origin { - path: "file1.rs", - pos: None, - header_type: Initial, - }, - ), - Source { - lineno: None, - inline_marks: [], - line: Empty, - }, - Source { - lineno: Some( - 5402, - ), - inline_marks: [], - line: Content { - text: "This is slice 1", - range: ( - 0, - 15, - ), - }, - }, - Source { - lineno: None, - inline_marks: [], - line: Empty, - }, - Raw( - Origin { - path: "file2.rs", - pos: None, - header_type: Continuation, - }, - ), - Source { - lineno: None, - inline_marks: [], - line: Empty, - }, - Source { - lineno: Some( - 2, - ), - inline_marks: [], - line: Content { - text: "This is slice 2", - range: ( - 0, - 15, - ), - }, - }, - Source { - lineno: None, - inline_marks: [], - line: Empty, - }, - ], - anonymized_line_numbers: false, - } - "#]]; - assert_eq( - output, - DisplayList::new(input, &STYLESHEET, false, None).to_debug(), - ); - } - - #[test] - fn test_format_slice_annotation_standalone() { - let line_1 = "This is line 1"; - let line_2 = "This is line 2"; - let source = [line_1, line_2].join("\n"); - // In line 2 - let range = 22..24; - let input = snippet::Level::Error.title("").snippet( - snippet::Snippet::source(&source) - .line_start(5402) - .annotation( - snippet::Level::Info - .span(range.clone()) - .label("Test annotation"), - ), - ); - let output = str![[r#" - DisplayList { - body: [ - Raw( - Annotation { - annotation: Annotation { - annotation_type: Error, - id: None, - label: [ - DisplayTextFragment { - content: "", - style: Emphasis, - }, - ], - }, - source_aligned: false, - continuation: false, - }, - ), - Source { - lineno: None, - inline_marks: [], - line: Empty, - }, - Source { - lineno: Some( - 5402, - ), - inline_marks: [], - line: Content { - text: "This is line 1", - range: ( - 0, - 14, - ), - }, - }, - Source { - lineno: Some( - 5403, - ), - inline_marks: [], - line: Content { - text: "This is line 2", - range: ( - 15, - 29, - ), - }, - }, - Source { - lineno: None, - inline_marks: [], - line: Annotation { - annotation: Annotation { - annotation_type: Info, - id: None, - label: [ - DisplayTextFragment { - content: "Test annotation", - style: Regular, - }, - ], - }, - range: ( - 7, - 9, - ), - annotation_type: Info, - annotation_part: Standalone, - }, - }, - Source { - lineno: None, - inline_marks: [], - line: Empty, - }, - ], - anonymized_line_numbers: false, - } - "#]]; - assert_eq( - output, - DisplayList::new(input, &STYLESHEET, false, None).to_debug(), - ); - } - - #[test] - fn test_format_label() { - let input = snippet::Level::Error - .title("") - .footer(snippet::Level::Error.title("This __is__ a title")); - let output = str![[r#" - DisplayList { - body: [ - Raw( - Annotation { - annotation: Annotation { - annotation_type: Error, - id: None, - label: [ - DisplayTextFragment { - content: "", - style: Emphasis, - }, - ], - }, - source_aligned: false, - continuation: false, - }, - ), - Raw( - Annotation { - annotation: Annotation { - annotation_type: Error, - id: None, - label: [ - DisplayTextFragment { - content: "This __is__ a title", - style: Regular, - }, - ], - }, - source_aligned: true, - continuation: false, - }, - ), - ], - anonymized_line_numbers: false, - } - "#]]; - assert_eq( - output, - DisplayList::new(input, &STYLESHEET, false, None).to_debug(), - ); - } - - #[test] - #[should_panic] - fn test_i26() { - let source = "short"; - let label = "label"; - let input = snippet::Level::Error.title("").snippet( - snippet::Snippet::source(source) - .line_start(0) - .annotation(snippet::Level::Error.span(0..source.len() + 2).label(label)), - ); - let _ = DisplayList::new(input, &STYLESHEET, false, None); - } - - #[test] - fn test_i_29() { - let input = snippet::Level::Error.title("oops").snippet( - snippet::Snippet::source("First line\r\nSecond oops line") - .line_start(1) - .origin("") - .fold(true) - .annotation(snippet::Level::Error.span(19..23).label("oops")), - ); - let output = str![[r#" - DisplayList { - body: [ - Raw( - Annotation { - annotation: Annotation { - annotation_type: Error, - id: None, - label: [ - DisplayTextFragment { - content: "oops", - style: Emphasis, - }, - ], - }, - source_aligned: false, - continuation: false, - }, - ), - Raw( - Origin { - path: "", - pos: Some( - ( - 2, - 8, - ), - ), - header_type: Initial, - }, - ), - Source { - lineno: None, - inline_marks: [], - line: Empty, - }, - Source { - lineno: Some( - 1, - ), - inline_marks: [], - line: Content { - text: "First line", - range: ( - 0, - 10, - ), - }, - }, - Source { - lineno: Some( - 2, - ), - inline_marks: [], - line: Content { - text: "Second oops line", - range: ( - 12, - 28, - ), - }, - }, - Source { - lineno: None, - inline_marks: [], - line: Annotation { - annotation: Annotation { - annotation_type: None, - id: None, - label: [ - DisplayTextFragment { - content: "oops", - style: Regular, - }, - ], - }, - range: ( - 7, - 11, - ), - annotation_type: Error, - annotation_part: Standalone, - }, - }, - Source { - lineno: None, - inline_marks: [], - line: Empty, - }, - ], - anonymized_line_numbers: false, - } - "#]]; - assert_eq( - output, - DisplayList::new(input, &STYLESHEET, false, None).to_debug(), - ); - } - - #[test] - fn test_source_empty() { - let dl = from_display_lines(vec![DisplayLine::Source { - lineno: None, - inline_marks: vec![], - line: DisplaySourceLine::Empty, - }]); - - assert_eq(str![" |"], dl.to_string()); - } - - #[test] - fn test_source_content() { - let dl = from_display_lines(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( - str![[r#" - 56 | This is an example - 57 | of content lines"#]], - dl.to_string(), - ); - } - - #[test] - fn test_source_annotation_standalone_singleline() { - let dl = from_display_lines(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(str![" | ^^^^^ Example string"], dl.to_string()); - } - - #[test] - fn test_source_annotation_standalone_multiline() { - let dl = from_display_lines(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( - str![[r#" - | ----- help: Example string - | Second line"#]] - .indent(false), - dl.to_string(), - ); - } - - #[test] - fn test_source_annotation_standalone_multi_annotation() { - let dl = from_display_lines(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: "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( - str![[r#" - | ----- info: Example string - | Second line - | Second line of the warning - | ----- info: This is an info - | ----- help: This is help - | This is an annotation of type none"#]] - .indent(false), - dl.to_string(), - ); - } - - #[test] - fn test_fold_line() { - let dl = from_display_lines(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( - str![[r#" - 5 | This is line 5 - ... - 10021 | ... and now we're at line 10021"#]], - dl.to_string(), - ); - } - - #[test] - fn test_raw_origin_initial_nopos() { - let dl = from_display_lines(vec![DisplayLine::Raw(DisplayRawLine::Origin { - path: "src/test.rs", - pos: None, - header_type: DisplayHeaderType::Initial, - })]); - - assert_eq(str!["--> src/test.rs"], dl.to_string()); - } - - #[test] - fn test_raw_origin_initial_pos() { - let dl = from_display_lines(vec![DisplayLine::Raw(DisplayRawLine::Origin { - path: "src/test.rs", - pos: Some((23, 15)), - header_type: DisplayHeaderType::Initial, - })]); - - assert_eq(str!["--> src/test.rs:23:15"], dl.to_string()); - } - - #[test] - fn test_raw_origin_continuation() { - let dl = from_display_lines(vec![DisplayLine::Raw(DisplayRawLine::Origin { - path: "src/test.rs", - pos: Some((23, 15)), - header_type: DisplayHeaderType::Continuation, - })]); - - assert_eq(str!["::: src/test.rs:23:15"], dl.to_string()); - } - - #[test] - fn test_raw_annotation_unaligned() { - let dl = from_display_lines(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(str!["error[E0001]: This is an error"], dl.to_string()); - } - - #[test] - fn test_raw_annotation_unaligned_multiline() { - let dl = from_display_lines(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( - str![[r#" - warning[E0001]: This is an error - Second line of the error"#]], - dl.to_string(), - ); - } - - #[test] - fn test_raw_annotation_aligned() { - let dl = from_display_lines(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(str![" = error[E0001]: This is an error"], dl.to_string()); - } - - #[test] - fn test_raw_annotation_aligned_multiline() { - let dl = from_display_lines(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( - str![[r#" - = warning[E0001]: This is an error - Second line of the error"#]] - .indent(false), - dl.to_string(), - ); - } - - #[test] - fn test_different_annotation_types() { - let dl = from_display_lines(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( - str![[r#" - note: This is a note - This is just a string - Second line of none type annotation"#]], - dl.to_string(), - ); - } - - #[test] - fn test_inline_marks_empty_line() { - let dl = from_display_lines(vec![DisplayLine::Source { - lineno: None, - inline_marks: vec![DisplayMark { - mark_type: DisplayMarkType::AnnotationThrough, - annotation_type: DisplayAnnotationType::Error, - }], - line: DisplaySourceLine::Empty, - }]); - - assert_eq(str![[" | |"]], dl.to_string()); - } - - #[test] - fn test_anon_lines() { - let mut dl = from_display_lines(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( - str![[r#" - LL | This is an example - LL | of content lines - | - | abc"#]], - dl.to_string(), - ); - } - - #[test] - fn test_raw_origin_initial_pos_anon_lines() { - let mut dl = from_display_lines(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 initial position - dl.anonymized_line_numbers = true; - assert_eq(str!["--> src/test.rs:23:15"], dl.to_string()); - } -} diff --git a/tests/formatter.rs b/tests/formatter.rs index 035492a..3b02489 100644 --- a/tests/formatter.rs +++ b/tests/formatter.rs @@ -1,5 +1,7 @@ use annotate_snippets::{Level, Renderer, Snippet}; +use snapbox::{assert_eq, str}; + #[test] fn test_i_29() { let snippets = Level::Error.title("oops").snippet( @@ -8,16 +10,18 @@ fn test_i_29() { .annotation(Level::Error.span(19..23).label("oops")) .fold(true), ); - let expected = r#"error: oops + let expected = str![[r#" +error: oops --> :2:8 | 1 | First line 2 | Second oops line | ^^^^ oops - |"#; + |"#]] + .indent(false); let renderer = Renderer::plain(); - assert_eq!(renderer.render(snippets).to_string(), expected); + assert_eq(expected, renderer.render(snippets).to_string()); } #[test] @@ -28,15 +32,17 @@ fn test_point_to_double_width_characters() { .annotation(Level::Error.span(18..24).label("world")), ); - let expected = r#"error + let expected = str![[r#" +error --> :1:7 | 1 | こんにちは、世界 | ^^^^ world - |"#; + |"#]] + .indent(false); let renderer = Renderer::plain(); - assert_eq!(renderer.render(snippets).to_string(), expected); + assert_eq(expected, renderer.render(snippets).to_string()); } #[test] @@ -47,17 +53,19 @@ fn test_point_to_double_width_characters_across_lines() { .annotation(Level::Error.span(6..22).label("Good morning")), ); - let expected = r#"error + let expected = str![[r#" +error --> :1:3 | 1 | おはよう | _____^ 2 | | ございます | |______^ Good morning - |"#; + |"#]] + .indent(false); let renderer = Renderer::plain(); - assert_eq!(renderer.render(snippets).to_string(), expected); + assert_eq(expected, renderer.render(snippets).to_string()); } #[test] @@ -69,17 +77,19 @@ fn test_point_to_double_width_characters_multiple() { .annotation(Level::Note.span(16..22).label("Sushi2")), ); - let expected = r#"error + let expected = str![[r#" +error --> :1:1 | 1 | お寿司 | ^^^^^^ Sushi1 2 | 食べたい🍣 | ---- note: Sushi2 - |"#; + |"#]] + .indent(false); let renderer = Renderer::plain(); - assert_eq!(renderer.render(snippets).to_string(), expected); + assert_eq(expected, renderer.render(snippets).to_string()); } #[test] @@ -90,13 +100,207 @@ fn test_point_to_double_width_characters_mixed() { .annotation(Level::Error.span(18..32).label("New world")), ); - let expected = r#"error + let expected = str![[r#" +error --> :1:7 | 1 | こんにちは、新しいWorld! | ^^^^^^^^^^^ New world - |"#; + |"#]] + .indent(false); + + let renderer = Renderer::plain(); + assert_eq(expected, renderer.render(snippets).to_string()); +} + +#[test] +fn test_format_title() { + let input = Level::Error.title("This is a title").id("E0001"); + + let expected = str![r#"error[E0001]: This is a title"#]; + let renderer = Renderer::plain(); + assert_eq(expected, renderer.render(input).to_string()); +} + +#[test] +fn test_format_snippet_only() { + let source = "This is line 1\nThis is line 2"; + let input = Level::Error + .title("") + .snippet(Snippet::source(source).line_start(5402)); + + let expected = str![[r#" +error + | +5402 | This is line 1 +5403 | This is line 2 + |"#]] + .indent(false); + let renderer = Renderer::plain(); + assert_eq(expected, renderer.render(input).to_string()); +} + +#[test] +fn test_format_snippets_continuation() { + let src_0 = "This is slice 1"; + let src_1 = "This is slice 2"; + let input = Level::Error + .title("") + .snippet(Snippet::source(src_0).line_start(5402).origin("file1.rs")) + .snippet(Snippet::source(src_1).line_start(2).origin("file2.rs")); + let expected = str![[r#" +error + --> file1.rs + | +5402 | This is slice 1 + | + ::: file2.rs + | + 2 | This is slice 2 + |"#]] + .indent(false); + let renderer = Renderer::plain(); + assert_eq(expected, renderer.render(input).to_string()); +} + +#[test] +fn test_format_snippet_annotation_standalone() { + let line_1 = "This is line 1"; + let line_2 = "This is line 2"; + let source = [line_1, line_2].join("\n"); + // In line 2 + let range = 22..24; + let input = Level::Error.title("").snippet( + Snippet::source(&source) + .line_start(5402) + .annotation(Level::Info.span(range.clone()).label("Test annotation")), + ); + let expected = str![[r#" +error + | +5402 | This is line 1 +5403 | This is line 2 + | -- info: Test annotation + |"#]] + .indent(false); + let renderer = Renderer::plain(); + assert_eq(expected, renderer.render(input).to_string()); +} + +#[test] +fn test_format_footer_title() { + let input = Level::Error + .title("") + .footer(Level::Error.title("This __is__ a title")); + let expected = str![[r#" +error + = error: This __is__ a title"#]] + .indent(false); + let renderer = Renderer::plain(); + assert_eq(expected, renderer.render(input).to_string()); +} + +#[test] +#[should_panic] +fn test_i26() { + let source = "short"; + let label = "label"; + let input = Level::Error.title("").snippet( + Snippet::source(source) + .line_start(0) + .annotation(Level::Error.span(0..source.len() + 2).label(label)), + ); + let renderer = Renderer::plain(); + let _ = renderer.render(input).to_string(); +} + +#[test] +fn test_source_content() { + let source = "This is an example\nof content lines"; + let input = Level::Error + .title("") + .snippet(Snippet::source(source).line_start(56)); + let expected = str![[r#" +error + | +56 | This is an example +57 | of content lines + |"#]] + .indent(false); + let renderer = Renderer::plain(); + assert_eq(expected, renderer.render(input).to_string()); +} + +#[test] +fn test_source_annotation_standalone_singleline() { + let source = "tests"; + let input = Level::Error.title("").snippet( + Snippet::source(source) + .line_start(1) + .annotation(Level::Help.span(0..5).label("Example string")), + ); + let expected = str![[r#" +error + | +1 | tests + | ----- help: Example string + |"#]] + .indent(false); + let renderer = Renderer::plain(); + assert_eq(expected, renderer.render(input).to_string()); +} +#[test] +fn test_source_annotation_standalone_multiline() { + let source = "tests"; + let input = Level::Error.title("").snippet( + Snippet::source(source) + .line_start(1) + .annotation(Level::Help.span(0..5).label("Example string")) + .annotation(Level::Help.span(0..5).label("Second line")), + ); + let expected = str![[r#" +error + | +1 | tests + | ----- help: Example string + | ----- help: Second line + |"#]] + .indent(false); let renderer = Renderer::plain(); - assert_eq!(renderer.render(snippets).to_string(), expected); + assert_eq(expected, renderer.render(input).to_string()); +} + +#[test] +fn test_only_source() { + let input = Level::Error + .title("") + .snippet(Snippet::source("").origin("file.rs")); + let expected = str![[r#" +error +--> file.rs + | + |"#]] + .indent(false); + let renderer = Renderer::plain(); + assert_eq(expected, renderer.render(input).to_string()); +} + +#[test] +fn test_anon_lines() { + let source = "This is an example\nof content lines\n\nabc"; + let input = Level::Error + .title("") + .snippet(Snippet::source(source).line_start(56)); + let expected = str![[r#" +error + | +LL | This is an example +LL | of content lines +LL | +LL | abc + |"#]] + .indent(false); + let renderer = Renderer::plain().anonymized_line_numbers(true); + assert_eq(expected, renderer.render(input).to_string()); }