annotate-snippets-rs

Renders compiler-quality annotated diagnostic reports with source-span highlighting, multi-line underlines, and suggested patches.

Library
Cargo
v0.12.16
515stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
84/100Excellent
Development Activity100
Maintenance72
Community76
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
80/100Excellent
Architecture86
Code Quality92
Innovation78
Learning Curve65

annotate-snippets is the Rust library rust-lang uses to render rustc-style diagnostic output: multi-line source excerpts with highlighted spans, inline labels, gutter line numbers, and box-drawing decoration in both ASCII and Unicode. Rather than formatting an error as a flat string, callers build a Report out of Groups and Elements — a primary diagnostic group plus any number of secondary context or suggested-fix groups — and hand it to a Renderer that lays out the terminal output, correctly accounting for tabs, wide/zero-width Unicode characters, overlapping annotations, and line folding.

Its test suite is adapted directly from rustc’s own parser tests and cross-checked against consumers like the ruff Python linter, and the crate is no_std-capable (only alloc is required) with an optional simd feature for faster scanning. It’s the reference implementation for teams that want compiler-grade diagnostic formatting — precise span highlighting, patch suggestions, and folded/elided context — without hand-rolling ANSI layout logic themselves.

What You Get

  • A builder API (Group, Title, Snippet, Annotation, Patch, Origin) for composing diagnostic reports as data rather than formatted strings
  • A Renderer with both plain and ANSI-styled output, plus DecorStyle::Ascii/DecorStyle::Unicode box-drawing variants for different terminal capabilities
  • Correct handling of multi-width and zero-width Unicode characters, tabs, and overlapping spans when computing column alignment
  • Automatic folding of source lines with no annotations, with AnnotationKind::Visible to force specific context to stay shown
  • Patch/suggestion rendering that diffs a proposed replacement against the original span and displays it as an inline edit
  • no_std compatibility (via alloc) with an optional simd feature (backed by memchr) for faster line scanning

Common Use Cases

  • Rendering parser or type-checker errors in a custom compiler or interpreter with source-span highlighting
  • Formatting linter findings with precise column/line underlines and suggested auto-fixes
  • Building CLI tools that need rustc-quality error output instead of single-line messages
  • Presenting config-file or template validation errors with the offending span highlighted in context

Under The Hood

Architecture The crate is organized in three layers: snippet.rs defines the public, immutable builder API (Group, Title, Snippet, Annotation, Patch, Origin) that callers use to declaratively compose a Report (a slice of Groups); level.rs defines severity constants (Level::ERROR, WARNING, INFO, NOTE, HELP) used to construct titles and messages; and the renderer module (render.rs, source_map.rs, margin.rs, styled_buffer.rs, stylesheet.rs) performs the actual layout — computing gutter width, folding uninteresting lines, resolving multi-line span underlines, and reconciling Patch spans against the original source via a TrimmedPatch/SourceMap abstraction — before writing into a StyledBuffer and assembling the final String. Data flows one direction only: a caller builds an immutable Report, Renderer::render consumes it, and rendering has no side effects or global state, which keeps the core Group/Element/Annotation types as the one abstraction the rest of the crate depends on.

Tech Stack A Rust crate with MSRV 1.88.0, no_std-capable (alloc required, std behind a default feature flag). Runtime dependencies are minimal and mostly default-features = false: anstyle for ANSI styling primitives, unicode-width for correct multi-width character layout, and an optional memchr gated behind a simd feature for faster scanning. Dev-dependencies show a serious test/bench harness: divan for benchmarking, snapbox (with diff/term-svg/cmd/examples features) for snapshot-testing exact rendered output including SVG captures, and anstream for example output. Build tooling is stock Cargo with a workspace-level lint table and cargo-release metadata for changelog automation — no database or network dependency, since rendering is pure string transformation.

Code Quality The test suite includes tests/rustc_tests.rs, adapted directly from rustc’s own parser test suite, plus tests/formatter.rs, tests/ruff.rs, and a tests/color/ directory with dozens of paired .rs/.ascii.term.svg/.unicode.term.svg snapshot tests asserting exact rendered output via snapbox. Public types lean on #[non_exhaustive] enums (AnnotationKind, Element) and impl Into<Cow<...>> builder parameters to avoid unnecessary allocation, and doc comments consistently flag which inputs are treated as “untrusted” and normalized. CI runs a standard build/test workflow alongside a nightly-regression workflow, a cargo-audit dependency-vulnerability scan, commit-message linting, and a spelling check; the workspace enables dozens of explicit clippy warn-level lints. No test files were found to be missing coverage for core rendering paths — this is a professionally maintained crate validated against real downstream consumers (rustc, ruff).

What Makes It Unique This is the crate rust-lang itself uses to reproduce rustc’s diagnostic rendering — its test suite is adapted from rustc’s own parser tests, and it’s also exercised by the ruff Python linter. It handles problems most formatting or logging crates don’t attempt: correct column alignment across multi-width and zero-width Unicode, tab expansion, overlapping annotation spans, automatic folding of uninteresting source lines, and side-by-side patch/suggestion rendering with both ASCII and Unicode box-drawing decoration. Its Group/Element model explicitly distinguishes a “primary” diagnostic group from “secondary” context or suggested-fix groups, mirroring how compiler diagnostics are structured rather than treating an error as a single flat string.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search