From c8d8c65232cf988caa1a36d6cda2ee674548bc0b Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 11 Mar 2024 14:33:17 -0500 Subject: [PATCH 1/2] test(examples): Verify output --- Cargo.lock | 37 +++++++++++++++++ Cargo.toml | 3 +- examples/expected_type.rs | 4 +- examples/expected_type.svg | 44 ++++++++++++++++++++ examples/footer.rs | 4 +- examples/footer.svg | 43 +++++++++++++++++++ examples/format.rs | 4 +- examples/format.svg | 85 ++++++++++++++++++++++++++++++++++++++ examples/multislice.rs | 4 +- examples/multislice.svg | 44 ++++++++++++++++++++ tests/examples.rs | 37 +++++++++++++++++ 11 files changed, 300 insertions(+), 9 deletions(-) create mode 100644 examples/expected_type.svg create mode 100644 examples/footer.svg create mode 100644 examples/format.svg create mode 100644 examples/multislice.svg create mode 100644 tests/examples.rs diff --git a/Cargo.lock b/Cargo.lock index e507736f..5672f610 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,6 +21,7 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" name = "annotate-snippets" version = "0.10.2" dependencies = [ + "anstream", "anstyle", "criterion", "difference", @@ -336,6 +337,18 @@ dependencies = [ "rustversion", ] +[[package]] +name = "escargot" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f474c6844cbd04e783d0f25757583db4f491770ca618bedf2fb01815fc79939" +dependencies = [ + "log", + "once_cell", + "serde", + "serde_json", +] + [[package]] name = "fastrand" version = "2.0.1" @@ -542,6 +555,16 @@ version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +[[package]] +name = "os_pipe" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57119c3b893986491ec9aa85056780d3a0f3cf4da7cc09dd3650dbd6c6738fb9" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "plotters" version = "0.3.5" @@ -734,15 +757,20 @@ dependencies = [ "anstyle-svg", "content_inspector", "dunce", + "escargot", "filetime", "ignore", + "libc", "libtest-mimic", "normalize-line-endings", + "os_pipe", "serde_json", "similar", "snapbox-macros", "tempfile", + "wait-timeout", "walkdir", + "windows-sys 0.52.0", ] [[package]] @@ -844,6 +872,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "walkdir" version = "2.4.0" diff --git a/Cargo.toml b/Cargo.toml index 0b19a89f..5fbfc0b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,11 +29,12 @@ itertools = "0.12.1" unicode-width = "0.1.11" [dev-dependencies] +anstream = "0.6.13" criterion = "0.5.1" difference = "2.0.0" glob = "0.3.1" serde = { version = "1.0.197", features = ["derive"] } -snapbox = { version = "0.5.8", features = ["diff", "harness", "path", "term-svg"] } +snapbox = { version = "0.5.8", features = ["diff", "harness", "path", "term-svg", "cmd", "examples"] } toml = "0.5.11" [[bench]] diff --git a/examples/expected_type.rs b/examples/expected_type.rs index 99fb1bf7..adcbeff1 100644 --- a/examples/expected_type.rs +++ b/examples/expected_type.rs @@ -18,6 +18,6 @@ fn main() { .annotation(Label::info("while parsing this struct").span(34..50)), ); - let renderer = Renderer::plain(); - println!("{}", renderer.render(snippet)); + let renderer = Renderer::styled(); + anstream::println!("{}", renderer.render(snippet)); } diff --git a/examples/expected_type.svg b/examples/expected_type.svg new file mode 100644 index 00000000..ae065047 --- /dev/null +++ b/examples/expected_type.svg @@ -0,0 +1,44 @@ + + + + + + + error: expected type, found `22` + + --> examples/footer.rs:29:25 + + | + + 26 | annotations: vec![SourceAnnotation { + + | ---------------- info: while parsing this struct + + ... + + 29 | range: <22, 25>, + + | ^^ expected struct `annotate_snippets::snippet::Slice`, found reference + + | + + + + + + diff --git a/examples/footer.rs b/examples/footer.rs index d24b4973..6c45328a 100644 --- a/examples/footer.rs +++ b/examples/footer.rs @@ -17,6 +17,6 @@ fn main() { "expected type: `snippet::Annotation`\n found type: `__&__snippet::Annotation`", )); - let renderer = Renderer::plain(); - println!("{}", renderer.render(snippet)); + let renderer = Renderer::styled(); + anstream::println!("{}", renderer.render(snippet)); } diff --git a/examples/footer.svg b/examples/footer.svg new file mode 100644 index 00000000..34f81c8a --- /dev/null +++ b/examples/footer.svg @@ -0,0 +1,43 @@ + + + + + + + error[E0308]: mismatched types + + --> src/multislice.rs:13:22 + + | + + 13 | slices: vec!["A", + + | ^^^ expected struct `annotate_snippets::snippet::Slice`, found reference + + | + + = note: expected type: `snippet::Annotation` + + found type: `__&__snippet::Annotation` + + + + + + diff --git a/examples/format.rs b/examples/format.rs index 5eb5a287..1337812e 100644 --- a/examples/format.rs +++ b/examples/format.rs @@ -32,6 +32,6 @@ fn main() { .annotation(Label::error("expected enum `std::option::Option`").span(26..724)), ); - let renderer = Renderer::plain(); - println!("{}", renderer.render(snippet)); + let renderer = Renderer::styled(); + anstream::println!("{}", renderer.render(snippet)); } diff --git a/examples/format.svg b/examples/format.svg new file mode 100644 index 00000000..dd6c1c07 --- /dev/null +++ b/examples/format.svg @@ -0,0 +1,85 @@ + + + + + + + error[E0308]: mismatched types + + --> src/format.rs:51:6 + + | + + 51 | ) -> Option<String> { + + | -------------- expected `Option<String>` because of return type + + 52 | for ann in annotations { + + | _____^ + + 53 | | match (ann.range.0, ann.range.1) { + + 54 | | (None, None) => continue, + + 55 | | (Some(start), Some(end)) if start > end_index => continue, + + 56 | | (Some(start), Some(end)) if start >= start_index => { + + 57 | | let label = if let Some(ref label) = ann.label { + + 58 | | format!(" {}", label) + + 59 | | } else { + + 60 | | String::from("") + + 61 | | }; + + 62 | | + + 63 | | return Some(format!( + + 64 | | "{}{}{}", + + 65 | | " ".repeat(start - start_index), + + 66 | | "^".repeat(end - start), + + 67 | | label + + 68 | | )); + + 69 | | } + + 70 | | _ => continue, + + 71 | | } + + 72 | | } + + | |____^ expected enum `std::option::Option` + + | + + + + + + diff --git a/examples/multislice.rs b/examples/multislice.rs index f0de5579..b6fcb3f8 100644 --- a/examples/multislice.rs +++ b/examples/multislice.rs @@ -5,6 +5,6 @@ fn main() { .slice(Slice::new("Foo", 51).origin("src/format.rs")) .slice(Slice::new("Faa", 129).origin("src/display.rs")); - let renderer = Renderer::plain(); - println!("{}", renderer.render(snippet)); + let renderer = Renderer::styled(); + anstream::println!("{}", renderer.render(snippet)); } diff --git a/examples/multislice.svg b/examples/multislice.svg new file mode 100644 index 00000000..2ab959a3 --- /dev/null +++ b/examples/multislice.svg @@ -0,0 +1,44 @@ + + + + + + + error: mismatched types + + --> src/format.rs + + | + + 51 | Foo + + | + + ::: src/display.rs + + | + + 129 | Faa + + | + + + + + + diff --git a/tests/examples.rs b/tests/examples.rs new file mode 100644 index 00000000..6025f5e5 --- /dev/null +++ b/tests/examples.rs @@ -0,0 +1,37 @@ +#[test] +fn expected_type() { + let target = "expected_type"; + let expected = snapbox::file!["../examples/expected_type.svg": TermSvg]; + assert_example(target, expected); +} + +#[test] +fn footer() { + let target = "footer"; + let expected = snapbox::file!["../examples/footer.svg": TermSvg]; + assert_example(target, expected); +} + +#[test] +fn format() { + let target = "format"; + let expected = snapbox::file!["../examples/format.svg": TermSvg]; + assert_example(target, expected); +} + +#[test] +fn multislice() { + let target = "multislice"; + let expected = snapbox::file!["../examples/multislice.svg": TermSvg]; + assert_example(target, expected); +} + +#[track_caller] +fn assert_example(target: &str, expected: snapbox::Data) { + let bin_path = snapbox::cmd::compile_example(target, ["--features=testing-colors"]).unwrap(); + snapbox::cmd::Command::new(bin_path) + .env("CLICOLOR_FORCE", "1") + .assert() + .success() + .stdout_eq(expected); +} From 77050eafcfbadf42b5c8e09c892dadfc9e84753f Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 11 Mar 2024 14:39:11 -0500 Subject: [PATCH 2/2] docs: Shift example code from README to lib.rs We now pull from an example - We verify it builds (wasn't doing that with README) - We show the output for the actual code (couldn't do that from a rustdoc code fence) --- README.md | 65 ++++-------------------------------------------------- src/lib.rs | 18 ++++----------- 2 files changed, 8 insertions(+), 75 deletions(-) diff --git a/README.md b/README.md index f1b03522..21f95c4b 100644 --- a/README.md +++ b/README.md @@ -3,73 +3,14 @@ `annotate-snippets` is a Rust library for annotation of programming code slices. [![crates.io](https://img.shields.io/crates/v/annotate-snippets.svg)](https://crates.io/crates/annotate-snippets) +[![documentation](https://img.shields.io/badge/docs-master-blue.svg)][Documentation] ![build status](https://github.com/rust-lang/annotate-snippets-rs/actions/workflows/ci.yml/badge.svg) The library helps visualize meta information annotating source code slices. It takes a data structure called `Snippet` on the input and produces a `String` which may look like this: -```text -error[E0308]: mismatched types - --> src/format.rs:52:1 - | -51 | ) -> Option { - | -------------- expected `Option` because of return type -52 | / for ann in annotations { -53 | | match (ann.range.0, ann.range.1) { -54 | | (None, None) => continue, -55 | | (Some(start), Some(end)) if start > end_index => continue, -... | -71 | | } -72 | | } - | |_____^ expected enum `std::option::Option`, found () -``` - -[Documentation][] - -[Documentation]: https://docs.rs/annotate-snippets/ - -Usage ------ - -```rust -use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation}; - -fn main() { - let snippet = Snippet { - title: Some(Annotation { - label: Some("expected type, found `22`"), - id: None, - annotation_type: AnnotationType::Error, - }), - footer: vec![], - slices: vec![Slice { - source: r#" annotations: vec![SourceAnnotation { - label: "expected struct `annotate_snippets::snippet::Slice`, found reference" - , - range: <22, 25>,"#, - line_start: 26, - origin: Some("examples/footer.rs"), - fold: true, - annotations: vec![ - SourceAnnotation { - label: "", - annotation_type: AnnotationType::Error, - range: (193, 195), - }, - SourceAnnotation { - label: "while parsing this struct", - annotation_type: AnnotationType::Info, - range: (34, 50), - }, - ], - }], - }; - - let renderer = Renderer::plain(); - println!("{}", renderer.render(snippet)); -} -``` +![Screenshot](./examples/expected_type.svg) Local Development ----------------- @@ -80,3 +21,5 @@ Local Development When submitting a PR please use [`cargo fmt`][] (nightly). [`cargo fmt`]: https://github.com/rust-lang/rustfmt + +[Documentation]: https://docs.rs/annotate-snippets/ diff --git a/src/lib.rs b/src/lib.rs index 2066e671..8602c0a4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,22 +7,12 @@ //! //! # Example //! -//! ```text -//! error[E0308]: mismatched types -//! --> src/format.rs:52:1 -//! | -//! 51 | ) -> Option { -//! | -------------- expected `Option` because of return type -//! 52 | / for ann in annotations { -//! 53 | | match (ann.range.0, ann.range.1) { -//! 54 | | (None, None) => continue, -//! 55 | | (Some(start), Some(end)) if start > end_index => continue, -//! ... | -//! 71 | | } -//! 72 | | } -//! | |_____^ expected enum `std::option::Option`, found () +//! ```rust +#![doc = include_str!("../examples/expected_type.rs")] //! ``` //! +#![doc = include_str!("../examples/expected_type.svg")] +//! //! The crate uses a three stage process with two conversions between states: //! //! ```text