crates: vendor annotate-snippets crate

This merely adds the crate to our repository. Some cosmetic changes are
made to make it work in our repo and follow our conventions, such as
changing the name to `ruff_annotate_snippets`. We retain the original
license information. We do drop some things, such as benchmarks, but
keep tests and examples.
This commit is contained in:
Andrew Gallant 2024-12-20 12:55:16 -05:00 committed by Andrew Gallant
parent 4f3209a3ec
commit 9c27c57b5b
58 changed files with 6171 additions and 8 deletions

View file

@ -0,0 +1,783 @@
//! These tests have been adapted from [Rust's parser tests][parser-tests].
//!
//! [parser-tests]: https://github.com/rust-lang/rust/blob/894f7a4ba6554d3797404bbf550d9919df060b97/compiler/rustc_parse/src/parser/tests.rs
use ruff_annotate_snippets::{Level, Renderer, Snippet};
use snapbox::{assert_data_eq, str};
#[test]
fn ends_on_col0() {
let source = r#"
fn foo() {
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(10..13).label("test")),
);
let expected = str![[r#"
error: foo
--> test.rs:2:10
|
2 | fn foo() {
| __________^
3 | | }
| |_^ test
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn ends_on_col2() {
let source = r#"
fn foo() {
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(10..17).label("test")),
);
let expected = str![[r#"
error: foo
--> test.rs:2:10
|
2 | fn foo() {
| __________^
3 | |
4 | |
5 | | }
| |___^ test
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn non_nested() {
let source = r#"
fn foo() {
X0 Y0
X1 Y1
X2 Y2
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(14..32).label("`X` is a good letter"))
.annotation(
Level::Warning
.span(17..35)
.label("`Y` is a good letter too"),
),
);
let expected = str![[r#"
error: foo
--> test.rs:3:3
|
3 | X0 Y0
| ____^ -
| | ______|
4 | || X1 Y1
5 | || X2 Y2
| ||____^__- `Y` is a good letter too
| |_____|
| `X` is a good letter
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn nested() {
let source = r#"
fn foo() {
X0 Y0
Y1 X1
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(14..27).label("`X` is a good letter"))
.annotation(
Level::Warning
.span(17..24)
.label("`Y` is a good letter too"),
),
);
let expected = str![[r#"
error: foo
--> test.rs:3:3
|
3 | X0 Y0
| ____^ -
| | ______|
4 | || Y1 X1
| ||____-__^ `X` is a good letter
| |____|
| `Y` is a good letter too
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn different_overlap() {
let source = r#"
fn foo() {
X0 Y0 Z0
X1 Y1 Z1
X2 Y2 Z2
X3 Y3 Z3
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(17..38).label("`X` is a good letter"))
.annotation(
Level::Warning
.span(31..49)
.label("`Y` is a good letter too"),
),
);
let expected = str![[r#"
error: foo
--> test.rs:3:6
|
3 | X0 Y0 Z0
| _______^
4 | | X1 Y1 Z1
| | _________-
5 | || X2 Y2 Z2
| ||____^ `X` is a good letter
6 | | X3 Y3 Z3
| |____- `Y` is a good letter too
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn triple_overlap() {
let source = r#"
fn foo() {
X0 Y0 Z0
X1 Y1 Z1
X2 Y2 Z2
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(14..38).label("`X` is a good letter"))
.annotation(
Level::Warning
.span(17..41)
.label("`Y` is a good letter too"),
)
.annotation(Level::Warning.span(20..44).label("`Z` label")),
);
let expected = str![[r#"
error: foo
--> test.rs:3:3
|
3 | X0 Y0 Z0
| _____^ - -
| | _______| |
| || _________|
4 | ||| X1 Y1 Z1
5 | ||| X2 Y2 Z2
| |||____^__-__- `Z` label
| ||_____|__|
| |______| `Y` is a good letter too
| `X` is a good letter
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn triple_exact_overlap() {
let source = r#"
fn foo() {
X0 Y0 Z0
X1 Y1 Z1
X2 Y2 Z2
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(14..38).label("`X` is a good letter"))
.annotation(
Level::Warning
.span(14..38)
.label("`Y` is a good letter too"),
)
.annotation(Level::Warning.span(14..38).label("`Z` label")),
);
// This should have a `^` but we currently don't support the idea of a
// "primary" annotation, which would solve this
let expected = str![[r#"
error: foo
--> test.rs:3:3
|
3 | / X0 Y0 Z0
4 | | X1 Y1 Z1
5 | | X2 Y2 Z2
| | -
| |____|
| `X` is a good letter
| `Y` is a good letter too
| `Z` label
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn minimum_depth() {
let source = r#"
fn foo() {
X0 Y0 Z0
X1 Y1 Z1
X2 Y2 Z2
X3 Y3 Z3
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(17..27).label("`X` is a good letter"))
.annotation(
Level::Warning
.span(28..44)
.label("`Y` is a good letter too"),
)
.annotation(Level::Warning.span(36..52).label("`Z`")),
);
let expected = str![[r#"
error: foo
--> test.rs:3:6
|
3 | X0 Y0 Z0
| _______^
4 | | X1 Y1 Z1
| | ____^_-
| ||____|
| | `X` is a good letter
5 | | X2 Y2 Z2
| |___-______- `Y` is a good letter too
| ___|
| |
6 | | X3 Y3 Z3
| |_______- `Z`
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn non_overlapping() {
let source = r#"
fn foo() {
X0 Y0 Z0
X1 Y1 Z1
X2 Y2 Z2
X3 Y3 Z3
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(14..27).label("`X` is a good letter"))
.annotation(
Level::Warning
.span(39..55)
.label("`Y` is a good letter too"),
),
);
let expected = str![[r#"
error: foo
--> test.rs:3:3
|
3 | / X0 Y0 Z0
4 | | X1 Y1 Z1
| |____^ `X` is a good letter
5 | X2 Y2 Z2
| ______-
6 | | X3 Y3 Z3
| |__________- `Y` is a good letter too
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn overlapping_start_and_end() {
let source = r#"
fn foo() {
X0 Y0 Z0
X1 Y1 Z1
X2 Y2 Z2
X3 Y3 Z3
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(17..27).label("`X` is a good letter"))
.annotation(
Level::Warning
.span(31..55)
.label("`Y` is a good letter too"),
),
);
let expected = str![[r#"
error: foo
--> test.rs:3:6
|
3 | X0 Y0 Z0
| _______^
4 | | X1 Y1 Z1
| | ____^____-
| ||____|
| | `X` is a good letter
5 | | X2 Y2 Z2
6 | | X3 Y3 Z3
| |__________- `Y` is a good letter too
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn multiple_labels_primary_without_message() {
let source = r#"
fn foo() {
a { b { c } d }
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(18..25).label(""))
.annotation(Level::Warning.span(14..27).label("`a` is a good letter"))
.annotation(Level::Warning.span(22..23).label("")),
);
let expected = str![[r#"
error: foo
--> test.rs:3:7
|
3 | a { b { c } d }
| ----^^^^-^^-- `a` is a good letter
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn multiple_labels_secondary_without_message() {
let source = r#"
fn foo() {
a { b { c } d }
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(14..27).label("`a` is a good letter"))
.annotation(Level::Warning.span(18..25).label("")),
);
let expected = str![[r#"
error: foo
--> test.rs:3:3
|
3 | a { b { c } d }
| ^^^^-------^^ `a` is a good letter
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn multiple_labels_primary_without_message_2() {
let source = r#"
fn foo() {
a { b { c } d }
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(18..25).label("`b` is a good letter"))
.annotation(Level::Warning.span(14..27).label(""))
.annotation(Level::Warning.span(22..23).label("")),
);
let expected = str![[r#"
error: foo
--> test.rs:3:7
|
3 | a { b { c } d }
| ----^^^^-^^--
| |
| `b` is a good letter
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn multiple_labels_secondary_without_message_2() {
let source = r#"
fn foo() {
a { b { c } d }
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(14..27).label(""))
.annotation(Level::Warning.span(18..25).label("`b` is a good letter")),
);
let expected = str![[r#"
error: foo
--> test.rs:3:3
|
3 | a { b { c } d }
| ^^^^-------^^
| |
| `b` is a good letter
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn multiple_labels_secondary_without_message_3() {
let source = r#"
fn foo() {
a bc d
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(14..18).label("`a` is a good letter"))
.annotation(Level::Warning.span(18..22).label("")),
);
let expected = str![[r#"
error: foo
--> test.rs:3:3
|
3 | a bc d
| ^^^^----
| |
| `a` is a good letter
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn multiple_labels_without_message() {
let source = r#"
fn foo() {
a { b { c } d }
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(14..27).label(""))
.annotation(Level::Warning.span(18..25).label("")),
);
let expected = str![[r#"
error: foo
--> test.rs:3:3
|
3 | a { b { c } d }
| ^^^^-------^^
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn multiple_labels_without_message_2() {
let source = r#"
fn foo() {
a { b { c } d }
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(18..25).label(""))
.annotation(Level::Warning.span(14..27).label(""))
.annotation(Level::Warning.span(22..23).label("")),
);
let expected = str![[r#"
error: foo
--> test.rs:3:7
|
3 | a { b { c } d }
| ----^^^^-^^--
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn multiple_labels_with_message() {
let source = r#"
fn foo() {
a { b { c } d }
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(14..27).label("`a` is a good letter"))
.annotation(Level::Warning.span(18..25).label("`b` is a good letter")),
);
let expected = str![[r#"
error: foo
--> test.rs:3:3
|
3 | a { b { c } d }
| ^^^^-------^^
| | |
| | `b` is a good letter
| `a` is a good letter
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn ingle_label_with_message() {
let source = r#"
fn foo() {
a { b { c } d }
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(14..27).label("`a` is a good letter")),
);
let expected = str![[r#"
error: foo
--> test.rs:3:3
|
3 | a { b { c } d }
| ^^^^^^^^^^^^^ `a` is a good letter
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn single_label_without_message() {
let source = r#"
fn foo() {
a { b { c } d }
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(14..27).label("")),
);
let expected = str![[r#"
error: foo
--> test.rs:3:3
|
3 | a { b { c } d }
| ^^^^^^^^^^^^^
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn long_snippet() {
let source = r#"
fn foo() {
X0 Y0 Z0
X1 Y1 Z1
1
2
3
4
5
6
7
8
9
10
X2 Y2 Z2
X3 Y3 Z3
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(17..27).label("`X` is a good letter"))
.annotation(
Level::Warning
.span(31..76)
.label("`Y` is a good letter too"),
),
);
let expected = str![[r#"
error: foo
--> test.rs:3:6
|
3 | X0 Y0 Z0
| _______^
4 | | X1 Y1 Z1
| | ____^____-
| ||____|
| | `X` is a good letter
5 | | 1
... |
15 | | X2 Y2 Z2
16 | | X3 Y3 Z3
| |__________- `Y` is a good letter too
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}
#[test]
fn long_snippet_multiple_spans() {
let source = r#"
fn foo() {
X0 Y0 Z0
1
2
3
X1 Y1 Z1
4
5
6
X2 Y2 Z2
7
8
9
10
X3 Y3 Z3
}
"#;
let input = Level::Error.title("foo").snippet(
Snippet::source(source)
.line_start(1)
.origin("test.rs")
.fold(true)
.annotation(Level::Error.span(17..73).label("`Y` is a good letter"))
.annotation(
Level::Warning
.span(37..56)
.label("`Z` is a good letter too"),
),
);
let expected = str![[r#"
error: foo
--> test.rs:3:6
|
3 | X0 Y0 Z0
| _______^
4 | | 1
5 | | 2
6 | | 3
7 | | X1 Y1 Z1
| | _________-
8 | || 4
9 | || 5
10 | || 6
11 | || X2 Y2 Z2
| ||__________- `Z` is a good letter too
12 | | 7
... |
15 | | 10
16 | | X3 Y3 Z3
| |________^ `Y` is a good letter
|
"#]];
let renderer = Renderer::plain();
assert_data_eq!(renderer.render(input).to_string(), expected);
}