mirror of https://github.com/zkat/miette.git
feat(protocol): sketched out a basic protocol
This commit is contained in:
parent
f5f97fde5b
commit
e2387ce2ed
|
|
@ -0,0 +1,6 @@
|
||||||
|
#![doc = include_str!("../README.md")]
|
||||||
|
|
||||||
|
pub use protocol::*;
|
||||||
|
|
||||||
|
mod source_impls;
|
||||||
|
mod protocol;
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
use std::fmt::Display;
|
||||||
|
use std::io::{self, Read};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Adds rich metadata to your Error that can be used by [DiagnosticReporter] to print
|
||||||
|
really nice and human-friendly error messages.
|
||||||
|
*/
|
||||||
|
pub trait Diagnostic: std::error::Error + Send + Sync + 'static {
|
||||||
|
/// Unique diagnostic code that can be used to look up more information
|
||||||
|
/// about this Diagnostic. Ideally also globally unique, and documented in
|
||||||
|
/// the toplevel crate's documentation for easy searching. Rust path
|
||||||
|
/// format (`foo::bar::baz`) is recommended, but more classic codes like
|
||||||
|
/// `E0123` or Enums will work just fine.
|
||||||
|
fn code(&self) -> Box<dyn Display>;
|
||||||
|
|
||||||
|
/// Diagnostic severity. This may be used by [Reporter]s to change the
|
||||||
|
/// display format of this diagnostic.
|
||||||
|
fn severity(&self) -> Severity;
|
||||||
|
|
||||||
|
/// Additional help text related to this Diagnostic. Do you have any
|
||||||
|
/// advice for the poor soul who's just run into this issue?
|
||||||
|
fn help(&self) -> Option<Vec<Box<dyn Display>>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Additional contextual details. This is typically used for adding
|
||||||
|
/// marked-up source file output the way compilers often do.
|
||||||
|
fn details(&self) -> Option<&[DiagnosticDetail]> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Protocol for [Diagnostic] handlers, which are responsible for actually printing out Diagnostics.
|
||||||
|
|
||||||
|
Blatantly based on [EyreHandler](https://docs.rs/eyre/0.6.5/eyre/trait.EyreHandler.html) (thanks, Jane!)
|
||||||
|
*/
|
||||||
|
pub trait DiagnosticReporter: core::any::Any + Send + Sync {
|
||||||
|
/// Define the report format.
|
||||||
|
fn debug(
|
||||||
|
&self,
|
||||||
|
diagnostic: &(dyn Diagnostic),
|
||||||
|
f: &mut core::fmt::Formatter<'_>,
|
||||||
|
) -> core::fmt::Result;
|
||||||
|
|
||||||
|
/// Override for the `Display` format.
|
||||||
|
fn display(
|
||||||
|
&self,
|
||||||
|
diagnostic: &(dyn Diagnostic),
|
||||||
|
f: &mut core::fmt::Formatter<'_>,
|
||||||
|
) -> core::fmt::Result {
|
||||||
|
write!(f, "{}", diagnostic)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
[Diagnostic] severity. Intended to be used by [DiagnosticReporter] to change the
|
||||||
|
way different Diagnostics are displayed.
|
||||||
|
*/
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub enum Severity {
|
||||||
|
/// Critical failure. The program cannot continue.
|
||||||
|
Error,
|
||||||
|
/// Warning. Please take note.
|
||||||
|
Warning,
|
||||||
|
/// Just some help. Here's how you could be doing it better.
|
||||||
|
Advice,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Represents a readable source of some sort: a source file, a String, etc.
|
||||||
|
*/
|
||||||
|
pub trait Source {
|
||||||
|
/// Get a `Read`er from a given [Source].
|
||||||
|
fn open(&self) -> io::Result<Box<dyn Read>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Details and additional context to be displayed.
|
||||||
|
*/
|
||||||
|
pub struct DiagnosticDetail {
|
||||||
|
/// Explanation of this specific diagnostic detail.
|
||||||
|
pub message: Option<String>,
|
||||||
|
/// The "filename" for this diagnostic.
|
||||||
|
pub source_name: String,
|
||||||
|
/// A [Source] that can be used to read the actual text of a source.
|
||||||
|
pub source: Box<dyn Source>,
|
||||||
|
/// The primary [SourceSpan] where this diagnostic is located.
|
||||||
|
pub span: SourceSpan,
|
||||||
|
/// Additional [SourceSpan]s that can add secondary context.
|
||||||
|
pub other_spans: Option<Vec<SourceSpan>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Span within a [Source] with an associated message.
|
||||||
|
*/
|
||||||
|
pub struct SourceSpan {
|
||||||
|
/// A name for the thing this SourceSpan is actually pointing to.
|
||||||
|
pub label: String,
|
||||||
|
/// The start of the span.
|
||||||
|
pub start: SourceLocation,
|
||||||
|
/// The end of the span.
|
||||||
|
pub end: SourceLocation,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Specific location in a [SourceSpan]
|
||||||
|
*/
|
||||||
|
pub struct SourceLocation {
|
||||||
|
/// 0-indexed column of location.
|
||||||
|
pub column: usize,
|
||||||
|
/// 0-indexed line of location.
|
||||||
|
pub line: usize,
|
||||||
|
/// 0-indexed _character_ offset of location.
|
||||||
|
pub offset: usize,
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*!
|
||||||
|
Default trait implementations for [Source].
|
||||||
|
*/
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{Cursor, Read, Result};
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use crate::{Source};
|
||||||
|
|
||||||
|
impl Source for String {
|
||||||
|
fn open(&self) -> Result<Box<dyn Read>> {
|
||||||
|
Ok(Box::new(Cursor::new(self.clone())))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Source for Path {
|
||||||
|
fn open(&self) -> Result<Box<dyn Read>> {
|
||||||
|
Ok(Box::new(File::open(self)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Source for PathBuf {
|
||||||
|
fn open(&self) -> Result<Box<dyn Read>> {
|
||||||
|
Ok(Box::new(File::open(self)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue