A fancy diagnostics & error reporting crate

Overview

Ariadne

crates.io crates.io License actions-badge

A fancy compiler diagnostics crate.

Example

Ariadne supports arbitrary multi-line spans

See examples/ for more examples.

About

ariadne is a sister project of chumsky. Neither are dependent on one-another, but I'm working on both simultaneously and like to think that their features complement each other. If you're thinking of using ariadne to process your compiler's output, why not try using chumsky to process its input?

Features

  • Inline and multi-line labels capable of handling arbitrary configurations of spans
  • Multi-file errors
  • Generic across custom spans and file caches
  • A choice of character sets to ensure compatibility
  • Coloured labels & highlighting with 8-bit and 24-bit color support (thanks to yansi)
  • Label priority and ordering
  • Compact mode for smaller diagnostics
  • Correct handling of variable-width characters such as tabs
  • A ColorGenerator type that generates distinct colours for visual elements.
  • A plethora of other options (tab width, label attach points, underlines, etc.)

Planned Features

  • Improved layout planning & space usage
  • Non-ANSI terminal support
  • More accessibility options (screenreader-friendly mode, textured highlighting as an alternative to color, etc.)

Credit

Thanks to:

  • @brendanzab for their beautiful codespan crate that inspired me to try pushing the envelope of error diagnostics.

  • @estebank for showing innumerable people just how good compiler diagnostics can be through their work on Rust.

Comments
  • Use line numbers instead of character position

    Use line numbers instead of character position

    Is it possible to render errors based on line number and then the column? My parser resets the column position on each new line, so rendering errors is difficult since an error on the 4th line at column 4..5 is being rendered as the 4th and 5th characters in the entire source.

    enhancement 
    opened by ryangjchandler 4
  • Support for line offset

    Support for line offset

    I have a perhaps odd situation where I'm dealing with chunks of text out of a larger file, so to get the correct line number I need to add an offset value. I implemented this here https://github.com/olson-dan/ariadne/commit/3b66508bafd6de14f8c1c57546e9a5136d1cb861 but it seems like rustfmt made a mess of this commit. Are you interested in the change at all? Maybe adding a rustfmt config to the main branch could help with this type of situation.

    opened by olson-dan 3
  • Example in README does not render properly

    Example in README does not render properly

    Hey, I was trying to get started with Ariadne and grabbed an example from the README, but it does not render as expected:

    What I got:

    image

    What README shows:

    Ariadne supports arbitrary multi-line spans

    Tested with 0.1.5 and 0.1.3.

    I was about to open a PR to fix this, the spans are a bit behind for the example in README and examples/sample.rs, however, I just wanted to confirm, can you reproduce this?

    EDIT: updated image.

    opened by marcospb19 2
  • support byte spans

    support byte spans

    Currently spans in ariadne reference characters and not bytes. Because converting between char indices and byte indices can be cumbersome it would be nice if both variants would be supported.

    opened by herkhinah 1
  • proposal: add `Report::with_labels`

    proposal: add `Report::with_labels`

    This PR adds Report::with_labels, a chainable equivalent of Report::add_labels. This brings a minor DX improvement for the common use case where a report includes an iterable of errors, such as when parsing input with chumsky.

    Before

    if let Err(errors) = parser().parse(&input) {
        let mut report =
            Report::build(ReportKind::Error, &filename, 0).with_message("Error parsing file");
        report.add_labels(errors.iter().map(|error| {
            Label::new((&filename, error.span())).with_message(format!("{}", error))
        }));
        report
            .finish()
            .eprint((&filename, Source::from(&input)))
            .unwrap();
    }
    

    After

    if let Err(errors) = parser().parse(&input) {
        Report::build(ReportKind::Error, &filename, 0)
            .with_message("Error parsing file");
            .with_labels(errors.iter().map(|error| {
                Label::new((&filename, error.span())).with_message(format!("{}", error))
            }))
            .finish()
            .eprint((&filename, Source::from(&input)))
            .unwrap();
    }
    
    opened by superhawk610 1
  • Add support for unicode width

    Add support for unicode width

    In just testing some byte offset to char index conversion code, I noticed https://github.com/zesterer/ariadne/issues/41

    When testing with "πŸ¦€". Naively just modifying char_width() prints multiple instances of the unicode character in question. "πŸ¦€" becomes "πŸ¦€πŸ¦€",

    I left this behavior enabled for whitespace since I believe it is a part of the treatment of '\t' tab characters.

    This perhaps doesn't fully fix the issue as reported, they might need a boolean to Config setting, which sets things up to call either width and width_cjk, but I don't know the right behavior to shoot for regarding whitespace in cjk.

    opened by ratmice 1
  • Relax 'static lifetime on custom ReportKind name

    Relax 'static lifetime on custom ReportKind name

    I'm in the process of writing a Python wrapper for ariadne, but ReportKind::Custom has a member with a 'static lifetime, making it impossible to use across FFI boundaries. This change relaxes the 'static lifetime, making it possible to use ReportKind::Custom across FFI.

    opened by slavfox 1
  • Typo in README

    Typo in README

    Here is a most crucial contribution. I hope the feature improvements in this pull request really help make ariadne a better project overall. Jokes aside, thank you for the excellent work.

    opened by Moxinilian 1
  • Bug:  weird visual bug when a label doesn't have a message

    Bug: weird visual bug when a label doesn't have a message

    OS: Windows Version of ariadne: I'm using git version

    minimal code:

    Report::build(ReportKind::Error, error.span.file_id, error.span.range.0)
    .with_code(1)
    .with_message(error.error_message)
    .with_label(Label::new(error.span).with_color(red))
    .finish()
    .print(sources(vec![("test.vnl", &self.source)]))
    .unwrap();
    

    output:

    opened by MordechaiHadad 1
  • Support for LSP?

    Support for LSP?

    I wonder how could this be integrated into LSP, to forward the diagnostics to the editor(s).

    P.D: Comming from https://www.reddit.com/r/rust/comments/okza9q/i_just_released_ariadne_a_crate_for_generating/h5bqd1j

    enhancement 
    opened by mamcx 1
  • Feature Request: Suggest an edit for note/help

    Feature Request: Suggest an edit for note/help

    Would be useful to be able to suggest edits in a note/help message similar to how rust does it.

    Need to be able to provide a new version of the line/file, not sure how that would work.

    enhancement 
    opened by Scoder12 1
  • Public types missing derivable traits

    Public types missing derivable traits

    Line, Source, FileCache, Label, Report, etc. do not implement any of Clone, Debug, PartialEq, etc.

    This makes it hard to use them in types that do need to implement those. Implementing them should be a trivial #[derive(…)] macro.

    See also C-COMMON-TRAITS in the Rust API Guidelines.

    enhancement help wanted good first issue 
    opened by recmo 1
  • `Config::default().with_color(false)` not disable colors

    `Config::default().with_color(false)` not disable colors

    Despite setting this to false, the colors are shown when added to labels:

    pub fn build_report(
        named: String,
        err: &ErrorParser,
    ) -> Report<(String, Range<usize>)> {
        let mut colors = ColorGenerator::new();
    
        // Generate some colours for each of our elements
        let primary = colors.next();
        // let secondary = colors.next();
        let code = err.error_code();
        let config = Config::default().with_color(false);
        let diagnostic = Report::build(ReportKind::Error, named.clone(), 0)
            .with_code(code as usize)
            .with_config(config);
    
        match err {
            ErrorParser::ScalarParse { span, kind, msg } => diagnostic
                .with_message(msg)
                .with_label(
                    Label::new((named, span.range()))
                        .with_message(msg)
                        .with_color(primary), <-- THIS CAUSE IT TO SHOW COLORS
                )
                .with_note(format!("Parsing value of type: {kind:?}"))
                .finish(),
            _ => {
                todo!()
            }
        }
    }
    
    bug good first issue 
    opened by mamcx 0
  • Reports with non-static labels

    Reports with non-static labels

    New to this crate, so not sure if I'm simply doing something wrong but it seems like you can't build reports with non-static values:

    Report::build(ReportKind::Error, ...)
        .with_message(...)
        with_label(Label::new((data.file.as_str(), span)))
    

    data.file is a String instance, my main function calls another function passing data which then builds the report. Borrowed data either escapes the function body or doesn't outlive 'static as required

    bug 
    opened by NViviers 0
  • Trailing whitespace characters

    Trailing whitespace characters

    Firstly thank you for the excellent library! We're heavily using it in PRQL.

    In PRQL we have a pre-commit action which removes trailing whitespace. It seems that ariadne's outputs have trailing whitespace, so inline snapshot tests can't pass. Here's an example: https://github.com/prql/prql/commit/80ae4319e1558e81025f6f72fe5f87f851e6fcda, from https://github.com/prql/prql/pull/1181.

    Would it be reasonable to strip trailing whitespace? Or is that too narrow a goal? It's not that critical for us; we can move to using snapshot tests in .snap files if needed.

    Thanks again

    opened by max-sixty 2
  • Labels without messages still create extra vertical space

    Labels without messages still create extra vertical space

    Consider this example:

    use ariadne::*;
    
    const TEXT: &str = "a b c d";
    
    fn report_n_labels(n: usize) {
        let mut report = Report::build(ReportKind::Error, (), 0);
        for i in 0..n {
            report = report.with_label(Label::new(i * 2..i * 2 + 1));
        }
        report.finish().print(Source::from(TEXT)).unwrap();
    }
    
    fn main() {
        for n in 1..=4 {
            report_n_labels(n);
        }
    }
    

    This gives output:

    Error: 
       ╭─[<unknown>:1:1]
       β”‚
     1 β”‚ a b c d
       Β· ─
       Β·
    ───╯
    Error:
       ╭─[<unknown>:1:1]
       β”‚
     1 β”‚ a b c d
       Β· ─ ─
       Β·
       Β·
       Β·
    ───╯
    Error:
       ╭─[<unknown>:1:1]
       β”‚
     1 β”‚ a b c d
       Β· ─ ─ ─
       Β·
       Β·
       Β·
       Β·
       Β·
    ───╯
    Error:
       ╭─[<unknown>:1:1]
       β”‚
     1 β”‚ a b c d
       Β· ─ ─ ─ ─
       Β·
       Β·
       Β·
       Β·
       Β·
       Β·
       Β·
    ───╯
    

    It looks like labels add extra vertical space for their messages even if they don't have messages. This occurs with compact mode too. I think this is undesirable.

    bug 
    opened by kaikalii 1
Owner
Joshua Barretto
Interested in things. He/him.
Joshua Barretto
Add nice user-facing diagnostics to your errors without being weird about it.

thisdiagnostic is a Rust library for adding rich diagnostic metadata to errors, for some really fancy and customizable error reporting!

Kat MarchΓ‘n 14 Feb 2, 2022
Minimal virus genome coverage assessment for metagenomic diagnostics

vircov Minimal virus genome coverage assessment for metagenomic diagnostics Overview v0.5.0 Purpose Implementation Installation Usage Tests Concept Cl

Eike Steinig 14 Oct 17, 2022
A special web app to render fancy UTF-8 sequences. :hindu_temple: :scroll:

UTF RENDER ?? ?? A special web app to render fancy UTF-8 sequences. ?? ?? ABOUT ?? Emojis and fancy symbols are part of the UTF-8 character standard (

✭ ANGEL DOLLFACE ✭ 4 Jan 15, 2023
Error propagation tracing in Rust.

Propagate Error propagation tracing in Rust. Why Propagate? Being able to trace the cause of an error is critical for many types of software written i

Ben Reeves 10 Sep 23, 2021
Better error messages for axum framework.

axum-debug This is a debugging crate that provides better error messages for axum framework. axum is a great framework for developing web applications

Eray Karatay 3 Feb 3, 2022
my attempt at compromise between unwrapping and bullying my dependencies' authors for Error impl

string-eyre Has this happened to you? error[E0599]: the method `wrap_err` exists for enum `Result<(), tauri::Error>`, but its trait bounds were not sa

MichaΕ‚ Sidor 1 Nov 25, 2021
Error context library with support for type-erased sources and backtraces, targeting full support of all features on stable Rust

Error context library with support for type-erased sources and backtraces, targeting full support of all features on stable Rust, and with an eye towards serializing runtime errors using serde.

Findora Foundation 1 Feb 12, 2022
Rust Util Collection, a simple and friendly error-chain

RUC Rust Util Collection, a simple and friendly error-chain, with many useful utils as an addition. The painful experience of using error-chain gave b

ζΌ’ 8 Dec 8, 2022
Rust Util Collection, a simple and friendly error-chain, with many useful utils as an addition.

RUC Rust Util Collection, a simple and friendly error-chain, with many useful utils as an addition. The painful experience of using error-chain gave b

ζΌ’ 6 Mar 27, 2022
Rust crate which provides direct access to files within a Debian archive

debarchive This Rust crate provides direct access to files within a Debian archive. This crate is used by our debrep utility to generate the Packages

Pop!_OS 11 Dec 18, 2021
microtemplate - A fast, microscopic helper crate for runtime string interpolation.

microtemplate A fast, microscopic helper crate for runtime string interpolation. Design Goals Very lightweight: I want microtemplate to do exactly one

_iPhoenix_ 13 Jan 31, 2022
Debug2 is a pretty printing crate based on std::fmt

debug2 is a pretty printing crate based on std::fmt Why not just use Debug The Debug trait is good, but the problem is it is not very good at n

Nixon Enraght-Moony 18 Jun 23, 2022
Granular locking crate for Rust

Granular locking crate for Rust. Instead of using coarse-grained Mutex or RwLock which can be used to lock an entire structure, glock provides more granular locking.

Ayman Madkour 9 Jul 22, 2022
A crate to implement leader election for Kubernetes workloads in Rust.

Kubernetes Leader Election in Rust This library provides simple leader election for Kubernetes workloads.

Hendrik Maus 33 Dec 29, 2022
This crate allows writing a struct in Rust and have it derive a struct of arrays layed out in memory according to the arrow format.

Arrow2-derive - derive for Arrow2 This crate allows writing a struct in Rust and have it derive a struct of arrays layed out in memory according to th

Jorge Leitao 29 Dec 27, 2022
Tiny Rust crate to iterate bit combinations

bit_combi_iter bit_combi_iter is a small dependency-free crate to enumerate all bit combinations less than given unsigned integer value keeping 1s in

Linda_pp 5 Apr 11, 2022
This crate bridges between gstreamer and tracing ecosystems.

This crate provides a bridge between gstreamer and the tracing ecosystem. The goal is to allow Rust applications utilizing GStreamer to better integra

Standard Cognition OSS 17 Jun 7, 2022
Membrane is an opinionated crate that generates a Dart package from a Rust library. Extremely fast performance with strict typing and zero copy returns over the FFI boundary via bincode.

Membrane is an opinionated crate that generates a Dart package from a Rust library. Extremely fast performance with strict typing and zero copy returns over the FFI boundary via bincode.

Jerel Unruh 70 Dec 13, 2022
Rust crate for reading SER files used in astrophotography

Rust crate for reading SER files used in astrophotography.

Andy Grove 2 Oct 4, 2021