use annotate_snippets::{Level, Renderer, Snippet};
use snapbox::{assert_data_eq, str};
#[test]
fn test_i_29() {
let snippets = Level::Error.title("oops").snippet(
Snippet::source("First line\r\nSecond oops line")
.origin("<current file>")
.annotation(Level::Error.span(19..23).label("oops"))
.fold(true),
);
let expected = str![[r#"
error: oops
--> <current file>:2:8
|
2 | Second oops line
| ^^^^ oops
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(snippets).to_string(), expected);
}
#[test]
fn test_point_to_double_width_characters() {
let snippets = Level::Error.title("").snippet(
Snippet::source("こんにちは、世界")
.origin("<current file>")
.annotation(Level::Error.span(18..24).label("world")),
);
let expected = str![[r#"
error
--> <current file>:1:7
|
1 | こんにちは、世界
| ^^^^ world
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(snippets).to_string(), expected);
}
#[test]
fn test_point_to_double_width_characters_across_lines() {
let snippets = Level::Error.title("").snippet(
Snippet::source("おはよう\nございます")
.origin("<current file>")
.annotation(Level::Error.span(6..22).label("Good morning")),
);
let expected = str![[r#"
error
--> <current file>:1:3
|
1 | おはよう
| _____^
2 | | ございます
| |______^ Good morning
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(snippets).to_string(), expected);
}
#[test]
fn test_point_to_double_width_characters_multiple() {
let snippets = Level::Error.title("").snippet(
Snippet::source("お寿司\n食べたい🍣")
.origin("<current file>")
.annotation(Level::Error.span(0..9).label("Sushi1"))
.annotation(Level::Note.span(16..22).label("Sushi2")),
);
let expected = str![[r#"
error
--> <current file>:1:1
|
1 | お寿司
| ^^^^^^ Sushi1
2 | 食べたい🍣
| ---- note: Sushi2
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(snippets).to_string(), expected);
}
#[test]
fn test_point_to_double_width_characters_mixed() {
let snippets = Level::Error.title("").snippet(
Snippet::source("こんにちは、新しいWorld!")
.origin("<current file>")
.annotation(Level::Error.span(18..32).label("New world")),
);
let expected = str![[r#"
error
--> <current file>:1:7
|
1 | こんにちは、新しいWorld!
| ^^^^^^^^^^^ New world
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(snippets).to_string(), expected);
}
#[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_data_eq!(renderer.render(input).to_string(), expected);
}
#[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
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[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
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[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");
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
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[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
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[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
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[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
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[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
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn test_only_source() {
let input = Level::Error
.title("")
.snippet(Snippet::source("").origin("file.rs"));
let expected = str![[r#"
error
--> file.rs
|
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[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
|
"#]];
let renderer = Renderer::plain().anonymized_line_numbers(true);
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn issue_130() {
let input = Level::Error.title("dummy").snippet(
Snippet::source("foo\nbar\nbaz")
.origin("file/path")
.line_start(3)
.fold(true)
.annotation(Level::Error.span(4..11)), );
let expected = str![[r#"
error: dummy
--> file/path:4:1
|
4 | / bar
5 | | baz
| |___^
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn unterminated_string_multiline() {
let source = "\
a\"
// ...
";
let input = Level::Error.title("").snippet(
Snippet::source(source)
.origin("file/path")
.line_start(3)
.fold(true)
.annotation(Level::Error.span(0..10)), );
let expected = str![[r#"
error
--> file/path:3:1
|
3 | / a"
4 | | // ...
| |_______^
|
"#]];
let renderer = Renderer::plain().anonymized_line_numbers(false);
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn char_and_nl_annotate_char() {
let source = "a\r\nb";
let input = Level::Error.title("").snippet(
Snippet::source(source)
.origin("file/path")
.line_start(3)
.annotation(Level::Error.span(0..2)), );
let expected = str![[r#"
error
--> file/path:3:1
|
3 | a
| ^
4 | b
|"#]];
let renderer = Renderer::plain().anonymized_line_numbers(false);
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn char_eol_annotate_char() {
let source = "a\r\nb";
let input = Level::Error.title("").snippet(
Snippet::source(source)
.origin("file/path")
.line_start(3)
.annotation(Level::Error.span(0..3)), );
let expected = str![[r#"
error
--> file/path:3:1
|
3 | a
| ^
4 | b
|"#]];
let renderer = Renderer::plain().anonymized_line_numbers(false);
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn char_eol_annotate_char_double_width() {
let snippets = Level::Error.title("").snippet(
Snippet::source("こん\r\nにちは\r\n世界")
.origin("<current file>")
.annotation(Level::Error.span(3..8)), );
let expected = str![[r#"
error
--> <current file>:1:2
|
1 | こん
| ^^
2 | にちは
3 | 世界
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(snippets).to_string(), expected);
}
#[test]
fn annotate_eol() {
let source = "a\r\nb";
let input = Level::Error.title("").snippet(
Snippet::source(source)
.origin("file/path")
.line_start(3)
.annotation(Level::Error.span(1..2)), );
let expected = str![[r#"
error
--> file/path:3:2
|
3 | a
| ^
4 | b
|"#]];
let renderer = Renderer::plain().anonymized_line_numbers(false);
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn annotate_eol2() {
let source = "a\r\nb";
let input = Level::Error.title("").snippet(
Snippet::source(source)
.origin("file/path")
.line_start(3)
.annotation(Level::Error.span(1..3)), );
let expected = str![[r#"
error
--> file/path:3:2
|
3 | a
| ^
4 | b
|"#]];
let renderer = Renderer::plain().anonymized_line_numbers(false);
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn annotate_eol3() {
let source = "a\r\nb";
let input = Level::Error.title("").snippet(
Snippet::source(source)
.origin("file/path")
.line_start(3)
.annotation(Level::Error.span(2..3)), );
let expected = str![[r#"
error
--> file/path:3:2
|
3 | a
| ^
4 | b
|"#]];
let renderer = Renderer::plain().anonymized_line_numbers(false);
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn annotate_eol4() {
let source = "a\r\nb";
let input = Level::Error.title("").snippet(
Snippet::source(source)
.origin("file/path")
.line_start(3)
.annotation(Level::Error.span(2..2)), );
let expected = str![[r#"
error
--> file/path:3:2
|
3 | a
| ^
4 | b
|"#]];
let renderer = Renderer::plain().anonymized_line_numbers(false);
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn annotate_eol_double_width() {
let snippets = Level::Error.title("").snippet(
Snippet::source("こん\r\nにちは\r\n世界")
.origin("<current file>")
.annotation(Level::Error.span(7..8)), );
let expected = str![[r#"
error
--> <current file>:1:3
|
1 | こん
| ^
2 | にちは
3 | 世界
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(snippets).to_string(), expected);
}
#[test]
fn multiline_eol_start() {
let source = "a\r\nb";
let input = Level::Error.title("").snippet(
Snippet::source(source)
.origin("file/path")
.line_start(3)
.annotation(Level::Error.span(1..4)), );
let expected = str![[r#"
error
--> file/path:3:2
|
3 | a
| __^
4 | | b
| |_^
|"#]];
let renderer = Renderer::plain().anonymized_line_numbers(false);
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn multiline_eol_start2() {
let source = "a\r\nb";
let input = Level::Error.title("").snippet(
Snippet::source(source)
.origin("file/path")
.line_start(3)
.annotation(Level::Error.span(2..4)), );
let expected = str![[r#"
error
--> file/path:3:2
|
3 | a
| __^
4 | | b
| |_^
|"#]];
let renderer = Renderer::plain().anonymized_line_numbers(false);
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn multiline_eol_start3() {
let source = "a\nb";
let input = Level::Error.title("").snippet(
Snippet::source(source)
.origin("file/path")
.line_start(3)
.annotation(Level::Error.span(1..3)), );
let expected = str![[r#"
error
--> file/path:3:2
|
3 | a
| __^
4 | | b
| |_^
|"#]];
let renderer = Renderer::plain().anonymized_line_numbers(false);
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn multiline_eol_start_double_width() {
let snippets = Level::Error.title("").snippet(
Snippet::source("こん\r\nにちは\r\n世界")
.origin("<current file>")
.annotation(Level::Error.span(7..11)), );
let expected = str![[r#"
error
--> <current file>:1:3
|
1 | こん
| _____^
2 | | にちは
| |__^
3 | 世界
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(snippets).to_string(), expected);
}
#[test]
fn multiline_eol_start_eol_end() {
let source = "a\nb\nc";
let input = Level::Error.title("").snippet(
Snippet::source(source)
.origin("file/path")
.line_start(3)
.annotation(Level::Error.span(1..4)), );
let expected = str![[r#"
error
--> file/path:3:2
|
3 | a
| __^
4 | | b
| |__^
5 | c
|
"#]];
let renderer = Renderer::plain().anonymized_line_numbers(false);
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn multiline_eol_start_eol_end2() {
let source = "a\r\nb\r\nc";
let input = Level::Error.title("").snippet(
Snippet::source(source)
.origin("file/path")
.line_start(3)
.annotation(Level::Error.span(2..5)), );
let expected = str![[r#"
error
--> file/path:3:2
|
3 | a
| __^
4 | | b
| |__^
5 | c
|
"#]];
let renderer = Renderer::plain().anonymized_line_numbers(false);
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn multiline_eol_start_eol_end3() {
let source = "a\r\nb\r\nc";
let input = Level::Error.title("").snippet(
Snippet::source(source)
.origin("file/path")
.line_start(3)
.annotation(Level::Error.span(2..6)), );
let expected = str![[r#"
error
--> file/path:3:2
|
3 | a
| __^
4 | | b
| |__^
5 | c
|
"#]];
let renderer = Renderer::plain().anonymized_line_numbers(false);
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn multiline_eol_start_eof_end() {
let source = "a\r\nb";
let input = Level::Error.title("").snippet(
Snippet::source(source)
.origin("file/path")
.line_start(3)
.annotation(Level::Error.span(1..5)), );
let expected = str![[r#"
error
--> file/path:3:2
|
3 | a
| __^
4 | | b
| |__^
|
"#]];
let renderer = Renderer::plain().anonymized_line_numbers(false);
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn multiline_eol_start_eof_end_double_width() {
let source = "ん\r\nに";
let input = Level::Error.title("").snippet(
Snippet::source(source)
.origin("file/path")
.line_start(3)
.annotation(Level::Error.span(3..9)), );
let expected = str![[r#"
error
--> file/path:3:2
|
3 | ん
| ___^
4 | | に
| |___^
|
"#]];
let renderer = Renderer::plain().anonymized_line_numbers(false);
assert_data_eq!(renderer.render(input).to_string(), expected);
}