Skip to main content

Render

Trait Render 

Source
pub trait Render {
    // Required methods
    fn render(&self, src: &str) -> String;
    fn render_indexed(&self, src: &str, index: &LineIndex) -> String;
}
Expand description

Rendering of a diagnostic-bearing value as a rustc-style snippet of its source. Implemented for Diagnostic and crate::Error.

Display stays the compact one-line form; Render::render draws the code, message, the labelled source lines with carets, help, path, and suggested fixes:

error[Y0027]: `: ` inside an unquoted value starts a nested mapping, which cannot begin on this line
 --> 1:4
  |
1 | a: b: c
  |    ^^^^
  |     - this `: ` starts a mapping
  |
  = help: to keep the `: ` as text, quote the whole value; …
  = suggestion: quote the value: replace `b: c` with `'b: c'`

§What is shown

  • Every label’s lines, in line order; lines that are not adjacent are separated by .... A label spanning several lines is drawn on its first line (to the end of the line) and on its last line (from the start of the line), with its message on the last one.
  • Primary labels are underlined with ^, secondary ones with -; an empty span (e.g. at the end of the input) gets one caret.
  • Tabs are shown as four spaces; wide characters (CJK, emoji) count two columns and combining marks none, so carets line up in a terminal. Control characters, bidirectional overrides and Unicode line separators are shown as \u{FFFD} so they cannot reorder or break the snippet. \n, \r\n and a lone \r all end a line (§5.4).
  • A line wider than 100 columns is cut to a window around its labels, marked with ... on the cut side.

§Cost

With an index (Render::render_indexed) a call costs O(labels × (log n + 100)) — the lines shown, never the input. Line starts and ends are found by scans capped at 1024 bytes, so a 100 MB single-line input costs the same as a short line. Render::render on a Diagnostic builds a LineIndex first (one O(n) pass); to render many diagnostics of one source, build the index once and use render_indexed. Error::render needs no index: an error already knows the line and column of its primary span, and other labels are numbered by counting line breaks from it.

§Robustness

Rendering never panics: spans past the end are clamped to it, spans off char boundaries are moved back to one, inverted spans are read as empty, and a LineIndex built from a different text only gives wrong line numbers.

use oneyaml::{Document, Render};

let src = "a: b: c\n";
let parsed = Document::parse_recovering(src);
let snippet = parsed.diagnostics()[0].render(src);
assert!(snippet.starts_with("error[Y0027]"));
assert!(snippet.contains("1 | a: b: c"));

To render many diagnostics of one source (a recovering parse’s, or the warnings from_str skips), build its LineIndex once and use Render::render_indexed:

use oneyaml::{Document, LineIndex, Render};

let src = "%YAML 1.1\n---\nquote: 'it's'\n";
let parsed = Document::parse_recovering(src);
let index = LineIndex::new(src);
let shown: Vec<String> = parsed
    .diagnostics()
    .iter()
    .map(|d| d.render_indexed(src, &index))
    .collect();
assert!(shown[0].starts_with("warning[Y1000]"));
assert!(shown[1].contains("write `''` for a literal `'`"));

// The strict entry points keep the warnings recorded before the error.
let err = oneyaml::from_str::<oneyaml::Value>(src).err().ok_or("expected an error")?;
assert_eq!(err.warnings()[0].code, oneyaml::code::YAML_VERSION_1_1);
assert!(err.render_indexed(src, &index).contains("3 | quote: 'it's'"));

With the miette feature, DiagnosticReport wraps any Diagnostic (with its source) as a miette::Diagnostic.

Required Methods§

Source

fn render(&self, src: &str) -> String

The snippet for src, the text the spans point into. Never panics, whatever src is (see the trait docs for the cost).

For a Diagnostic this builds a LineIndex of src on every call (O(n)): to render several diagnostics of one text, build the index once and call Render::render_indexed, or use Document::render_diagnostics / Parsed::render_diagnostics.

Source

fn render_indexed(&self, src: &str, index: &LineIndex) -> String

Render::render with line numbers from index, an index of src built once for many calls: O(lines shown), never O(input).

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§