mirror of https://github.com/zkat/miette.git
fix: address review feedback for no_std support
- Use core::error::Error directly (MSRV 1.82 supports it) - Remove build.rs (track_caller is always available with MSRV 1.82) - Simplify feature detection in handler.rs syscall module - Add clippy lints to catch std/core/alloc misuse - Remove custom StdError trait, re-export core::error::Error - Add __alloc module for derive macro compatibility - Clean up verbose comments - Remove extern crate alloc from tests (not needed with std) - Fix derive macros to use miette::__alloc paths
This commit is contained in:
parent
09e1090b2e
commit
c07cab4b60
10
Cargo.toml
10
Cargo.toml
|
|
@ -13,11 +13,11 @@ rust-version = "1.82.0"
|
|||
exclude = ["images/", "tests/", "miette-derive/"]
|
||||
|
||||
[dependencies]
|
||||
thiserror = "2.0.11"
|
||||
miette-derive = { path = "miette-derive", version = "=7.6.0", optional = true }
|
||||
unicode-width = { version = "0.2.0", default-features = false }
|
||||
cfg-if = "1.0.0"
|
||||
spin = { version = "0.9", default-features = false, features = ["mutex", "spin_mutex", "lazy"] }
|
||||
# spin is needed for no_std environments (provides Once without std)
|
||||
spin = { version = "0.9", default-features = false, features = ["once"] }
|
||||
|
||||
owo-colors = { version = "4.0.0", optional = true }
|
||||
textwrap = { version = "0.16.0", default-features = false, features = ["unicode-linebreak", "unicode-width"], optional = true }
|
||||
|
|
@ -31,6 +31,7 @@ serde = { version = "1.0.196", features = ["derive"], optional = true }
|
|||
syntect = { version = "5.1.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
thiserror = "2.0.11"
|
||||
semver = "1.0.21"
|
||||
futures = { version = "0.3", default-features = false }
|
||||
indenter = "0.3.3"
|
||||
|
|
@ -45,7 +46,7 @@ strip-ansi-escapes = "0.2.0"
|
|||
|
||||
[features]
|
||||
default = ["derive", "std"]
|
||||
std = ["thiserror/std", "fancy-no-syscall"]
|
||||
std = []
|
||||
derive = ["dep:miette-derive"]
|
||||
no-format-args-capture = []
|
||||
fancy-base = [
|
||||
|
|
@ -57,13 +58,14 @@ fancy-no-syscall = [
|
|||
]
|
||||
fancy-no-backtrace = [
|
||||
"fancy-base",
|
||||
"std",
|
||||
"dep:terminal_size",
|
||||
"dep:supports-hyperlinks",
|
||||
"dep:supports-color",
|
||||
"dep:supports-unicode",
|
||||
]
|
||||
fancy = ["fancy-no-backtrace", "dep:backtrace", "dep:backtrace-ext"]
|
||||
syntect-highlighter = ["fancy-no-backtrace", "dep:syntect", "std"]
|
||||
syntect-highlighter = ["fancy-no-backtrace", "dep:syntect"]
|
||||
|
||||
[workspace]
|
||||
members = ["miette-derive"]
|
||||
|
|
|
|||
6
build.rs
6
build.rs
|
|
@ -1,6 +0,0 @@
|
|||
fn main() {
|
||||
// track_caller is always available with our MSRV (Rust ≥ 1.82)
|
||||
|
||||
// Add check-cfg for conditional configurations
|
||||
println!("cargo:rustc-check-cfg=cfg(doc_cfg)");
|
||||
}
|
||||
|
|
@ -56,13 +56,13 @@ impl Code {
|
|||
let code = &code.as_ref()?.0;
|
||||
Some(match fields {
|
||||
syn::Fields::Named(_) => {
|
||||
quote! { Self::#ident { .. } => core::option::Option::Some(alloc::boxed::Box::new(#code)), }
|
||||
quote! { Self::#ident { .. } => core::option::Option::Some(miette::__alloc::Box::new(#code)), }
|
||||
}
|
||||
syn::Fields::Unnamed(_) => {
|
||||
quote! { Self::#ident(..) => core::option::Option::Some(alloc::boxed::Box::new(#code)), }
|
||||
quote! { Self::#ident(..) => core::option::Option::Some(miette::__alloc::Box::new(#code)), }
|
||||
}
|
||||
syn::Fields::Unit => {
|
||||
quote! { Self::#ident => core::option::Option::Some(alloc::boxed::Box::new(#code)), }
|
||||
quote! { Self::#ident => core::option::Option::Some(miette::__alloc::Box::new(#code)), }
|
||||
}
|
||||
})
|
||||
},
|
||||
|
|
@ -72,8 +72,8 @@ impl Code {
|
|||
pub(crate) fn gen_struct(&self) -> Option<TokenStream> {
|
||||
let code = &self.0;
|
||||
Some(quote! {
|
||||
fn code(&self) -> core::option::Option<alloc::boxed::Box<dyn core::fmt::Display + '_>> {
|
||||
core::option::Option::Some(alloc::boxed::Box::new(#code))
|
||||
fn code(&self) -> core::option::Option<miette::__alloc::Box<dyn core::fmt::Display + '_>> {
|
||||
core::option::Option::Some(miette::__alloc::Box::new(#code))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ impl DiagnosticSource {
|
|||
};
|
||||
quote! {
|
||||
Self::#ident #display_pat => {
|
||||
core::option::Option::Some(alloc::borrow::Borrow::borrow(#rel))
|
||||
core::option::Option::Some(miette::__alloc::borrow::Borrow::borrow(#rel))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -71,7 +71,7 @@ impl DiagnosticSource {
|
|||
let rel = &self.0;
|
||||
Some(quote! {
|
||||
fn diagnostic_source<'a>(&'a self) -> core::option::Option<&'a dyn miette::Diagnostic> {
|
||||
core::option::Option::Some(alloc::borrow::Borrow::borrow(&self.#rel))
|
||||
core::option::Option::Some(miette::__alloc::borrow::Borrow::borrow(&self.#rel))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,22 +58,22 @@ impl WhichFn {
|
|||
pub fn signature(&self) -> TokenStream {
|
||||
match self {
|
||||
Self::Code => quote! {
|
||||
fn code(& self) -> Option<alloc::boxed::Box<dyn core::fmt::Display + '_>>
|
||||
fn code(& self) -> Option<miette::__alloc::Box<dyn core::fmt::Display + '_>>
|
||||
},
|
||||
Self::Help => quote! {
|
||||
fn help(& self) -> Option<alloc::boxed::Box<dyn core::fmt::Display + '_>>
|
||||
fn help(& self) -> Option<miette::__alloc::Box<dyn core::fmt::Display + '_>>
|
||||
},
|
||||
Self::Url => quote! {
|
||||
fn url(& self) -> Option<alloc::boxed::Box<dyn core::fmt::Display + '_>>
|
||||
fn url(& self) -> Option<miette::__alloc::Box<dyn core::fmt::Display + '_>>
|
||||
},
|
||||
Self::Severity => quote! {
|
||||
fn severity(&self) -> Option<miette::Severity>
|
||||
},
|
||||
Self::Related => quote! {
|
||||
fn related(&self) -> Option<alloc::boxed::Box<dyn Iterator<Item = &dyn miette::Diagnostic> + '_>>
|
||||
fn related(&self) -> Option<miette::__alloc::Box<dyn Iterator<Item = &dyn miette::Diagnostic> + '_>>
|
||||
},
|
||||
Self::Labels => quote! {
|
||||
fn labels(&self) -> Option<alloc::boxed::Box<dyn Iterator<Item = miette::LabeledSpan> + '_>>
|
||||
fn labels(&self) -> Option<miette::__alloc::Box<dyn Iterator<Item = miette::LabeledSpan> + '_>>
|
||||
},
|
||||
Self::SourceCode => quote! {
|
||||
fn source_code(&self) -> Option<&dyn miette::SourceCode>
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ impl Help {
|
|||
Help::Display(display) => {
|
||||
let (fmt, args) = display.expand_shorthand_cloned(&display_members);
|
||||
Some(quote! {
|
||||
Self::#ident #display_pat => Option::Some(alloc::boxed::Box::new(format!(#fmt #args))),
|
||||
Self::#ident #display_pat => Option::Some(miette::__alloc::Box::new(format!(#fmt #args))),
|
||||
})
|
||||
}
|
||||
Help::Field(member, ty) => {
|
||||
|
|
@ -108,7 +108,7 @@ impl Help {
|
|||
Some(quote! {
|
||||
Self::#ident #display_pat => {
|
||||
use miette::macro_helpers::ToOption;
|
||||
miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(&#help).as_ref().map(|#var| -> alloc::boxed::Box<dyn core::fmt::Display + '_> { alloc::boxed::Box::new(format!("{}", #var)) })
|
||||
miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(&#help).as_ref().map(|#var| -> miette::__alloc::Box<dyn core::fmt::Display + '_> { miette::__alloc::Box::new(format!("{}", #var)) })
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
@ -123,21 +123,21 @@ impl Help {
|
|||
Help::Display(display) => {
|
||||
let (fmt, args) = display.expand_shorthand_cloned(&display_members);
|
||||
Some(quote! {
|
||||
fn help(&self) -> Option<alloc::boxed::Box<dyn core::fmt::Display + '_>> {
|
||||
fn help(&self) -> Option<miette::__alloc::Box<dyn core::fmt::Display + '_>> {
|
||||
#[allow(unused_variables, deprecated)]
|
||||
let Self #display_pat = self;
|
||||
Option::Some(alloc::boxed::Box::new(format!(#fmt #args)))
|
||||
Option::Some(miette::__alloc::Box::new(format!(#fmt #args)))
|
||||
}
|
||||
})
|
||||
}
|
||||
Help::Field(member, ty) => {
|
||||
let var = quote! { __miette_internal_var };
|
||||
Some(quote! {
|
||||
fn help(&self) -> Option<alloc::boxed::Box<dyn core::fmt::Display + '_>> {
|
||||
fn help(&self) -> Option<miette::__alloc::Box<dyn core::fmt::Display + '_>> {
|
||||
#[allow(unused_variables, deprecated)]
|
||||
let Self #display_pat = self;
|
||||
use miette::macro_helpers::ToOption;
|
||||
miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(&self.#member).as_ref().map(|#var| -> alloc::boxed::Box<dyn core::fmt::Display + '_> { alloc::boxed::Box::new(format!("{}", #var)) })
|
||||
miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(&self.#member).as_ref().map(|#var| -> miette::__alloc::Box<dyn core::fmt::Display + '_> { miette::__alloc::Box::new(format!("{}", #var)) })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ impl Labels {
|
|||
|
||||
Some(quote! {
|
||||
#[allow(unused_variables)]
|
||||
fn labels(&self) -> Option<alloc::boxed::Box<dyn Iterator<Item = miette::LabeledSpan> + '_>> {
|
||||
fn labels(&self) -> Option<miette::__alloc::Box<dyn Iterator<Item = miette::LabeledSpan> + '_>> {
|
||||
use miette::macro_helpers::ToOption;
|
||||
let Self #display_pat = self;
|
||||
|
||||
|
|
@ -236,7 +236,7 @@ impl Labels {
|
|||
.into_iter()
|
||||
#(#collections_chain)*;
|
||||
|
||||
Option::Some(alloc::boxed::Box::new(labels_iter.filter(Option::is_some).map(Option::unwrap)))
|
||||
Option::Some(miette::__alloc::Box::new(labels_iter.filter(Option::is_some).map(Option::unwrap)))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -322,7 +322,7 @@ impl Labels {
|
|||
]
|
||||
.into_iter()
|
||||
#(#collections_chain)*;
|
||||
Option::Some(alloc::boxed::Box::new(labels_iter.filter(Option::is_some).map(Option::unwrap)))
|
||||
Option::Some(miette::__alloc::Box::new(labels_iter.filter(Option::is_some).map(Option::unwrap)))
|
||||
}
|
||||
}),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ impl Related {
|
|||
};
|
||||
quote! {
|
||||
Self::#ident #display_pat => {
|
||||
Option::Some(alloc::boxed::Box::new(
|
||||
Option::Some(miette::__alloc::Box::new(
|
||||
#rel.iter().map(|x| -> &(dyn miette::Diagnostic) { &*x })
|
||||
))
|
||||
}
|
||||
|
|
@ -68,9 +68,9 @@ impl Related {
|
|||
pub(crate) fn gen_struct(&self) -> Option<TokenStream> {
|
||||
let rel = &self.0;
|
||||
Some(quote! {
|
||||
fn related<'a>(&'a self) -> Option<alloc::boxed::Box<dyn Iterator<Item = &'a dyn miette::Diagnostic> + 'a>> {
|
||||
use alloc::borrow::Borrow;
|
||||
Option::Some(alloc::boxed::Box::new(
|
||||
fn related<'a>(&'a self) -> Option<miette::__alloc::Box<dyn Iterator<Item = &'a dyn miette::Diagnostic> + 'a>> {
|
||||
use miette::__alloc::borrow::Borrow;
|
||||
Option::Some(miette::__alloc::Box::new(
|
||||
self.#rel.iter().map(|x| -> &(dyn miette::Diagnostic) { &*x.borrow() })
|
||||
))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ impl Url {
|
|||
}
|
||||
};
|
||||
Some(quote! {
|
||||
Self::#ident #pat => Option::Some(alloc::boxed::Box::new(format!(#fmt #args))),
|
||||
Self::#ident #pat => Option::Some(miette::__alloc::Box::new(format!(#fmt #args))),
|
||||
})
|
||||
},
|
||||
)
|
||||
|
|
@ -129,10 +129,10 @@ impl Url {
|
|||
}
|
||||
};
|
||||
Some(quote! {
|
||||
fn url(&self) -> Option<alloc::boxed::Box<dyn core::fmt::Display + '_>> {
|
||||
fn url(&self) -> Option<miette::__alloc::Box<dyn core::fmt::Display + '_>> {
|
||||
#[allow(unused_variables, deprecated)]
|
||||
let Self #pat = self;
|
||||
Option::Some(alloc::boxed::Box::new(format!(#fmt #args)))
|
||||
Option::Some(miette::__alloc::Box::new(format!(#fmt #args)))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ use core::{convert::Infallible, fmt::Display};
|
|||
|
||||
use crate::{Diagnostic, LabeledSpan, Severity, SourceCode};
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
impl crate::StdError for Infallible {}
|
||||
// Note: Infallible implements core::error::Error since Rust 1.81,
|
||||
// so we don't need to provide our own StdError impl.
|
||||
|
||||
impl Diagnostic for Infallible {
|
||||
fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,9 @@
|
|||
extern crate alloc;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use crate::StdError as Error;
|
||||
use alloc::boxed::Box;
|
||||
use core::error::Error;
|
||||
use core::fmt::{self, Display};
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error;
|
||||
#[cfg(feature = "std")]
|
||||
use std::io;
|
||||
|
||||
use crate::Diagnostic;
|
||||
|
|
@ -93,10 +90,7 @@ impl Diagnostic for MietteError {
|
|||
pub(crate) mod tests {
|
||||
#[cfg(not(feature = "std"))]
|
||||
use crate::StdError as Error;
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::string::ToString;
|
||||
#[cfg(feature = "std")]
|
||||
use std::string::ToString;
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
extern crate alloc;
|
||||
|
||||
use crate::StdError as Error;
|
||||
use alloc::boxed::Box;
|
||||
use core::error::Error;
|
||||
|
||||
use crate::{Diagnostic, Report};
|
||||
|
||||
|
|
@ -42,15 +42,6 @@ pub trait IntoDiagnostic<T, E> {
|
|||
fn into_diagnostic(self) -> Result<T, Report>;
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T, E: std::error::Error + Send + Sync + 'static> IntoDiagnostic<T, E> for Result<T, E> {
|
||||
#[track_caller]
|
||||
fn into_diagnostic(self) -> Result<T, Report> {
|
||||
self.map_err(|e| DiagnosticError(Box::new(e)).into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
impl<T, E: Error + Send + Sync + 'static> IntoDiagnostic<T, E> for Result<T, E> {
|
||||
#[track_caller]
|
||||
fn into_diagnostic(self) -> Result<T, Report> {
|
||||
|
|
@ -60,11 +51,13 @@ impl<T, E: Error + Send + Sync + 'static> IntoDiagnostic<T, E> for Result<T, E>
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::string::ToString;
|
||||
|
||||
use super::IntoDiagnostic;
|
||||
#[cfg(feature = "std")]
|
||||
use std::io::{self};
|
||||
#[cfg(feature = "std")]
|
||||
use std::string::ToString;
|
||||
use std::io;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use crate::error::tests::TestError;
|
||||
|
|
|
|||
|
|
@ -45,20 +45,14 @@
|
|||
// let error = $msg;
|
||||
// (&error).miette_kind().new(error)
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
extern crate alloc;
|
||||
|
||||
use super::Report;
|
||||
use alloc::boxed::Box;
|
||||
use core::fmt::{Debug, Display};
|
||||
|
||||
use super::Report;
|
||||
use crate::Diagnostic;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::boxed::Box;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::boxed::Box;
|
||||
|
||||
pub struct Adhoc;
|
||||
|
||||
pub trait AdhocKind: Sized {
|
||||
|
|
|
|||
|
|
@ -9,11 +9,9 @@ extern crate alloc;
|
|||
use alloc::boxed::Box;
|
||||
use core::fmt::Display;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use crate::StdError;
|
||||
use spin::Once;
|
||||
use core::error::Error as StdError;
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error as StdError;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
#[allow(unreachable_pub)]
|
||||
pub use into_diagnostic::*;
|
||||
|
|
@ -67,7 +65,11 @@ unsafe impl Send for Report {}
|
|||
pub type ErrorHook =
|
||||
Box<dyn Fn(&(dyn Diagnostic + 'static)) -> Box<dyn ReportHandler> + Sync + Send + 'static>;
|
||||
|
||||
static HOOK: Once<ErrorHook> = Once::new();
|
||||
#[cfg(feature = "std")]
|
||||
static HOOK: OnceLock<ErrorHook> = OnceLock::new();
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
static HOOK: spin::Once<ErrorHook> = spin::Once::new();
|
||||
|
||||
fn default_hook() -> ErrorHook {
|
||||
Box::new(get_default_printer)
|
||||
|
|
@ -87,39 +89,51 @@ impl core::fmt::Display for InstallError {
|
|||
impl StdError for InstallError {}
|
||||
impl Diagnostic for InstallError {}
|
||||
|
||||
/**
|
||||
Set the error hook.
|
||||
*/
|
||||
/// Set the error hook.
|
||||
#[cfg(feature = "std")]
|
||||
pub fn set_hook(hook: ErrorHook) -> Result<(), InstallError> {
|
||||
HOOK.set(hook).map_err(|_| InstallError)
|
||||
}
|
||||
|
||||
/// Set the error hook.
|
||||
#[cfg(not(feature = "std"))]
|
||||
pub fn set_hook(hook: ErrorHook) -> Result<(), InstallError> {
|
||||
HOOK.call_once(|| hook);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub(crate) fn capture_handler(error: &(dyn Diagnostic + 'static)) -> Box<dyn ReportHandler> {
|
||||
static DEFAULT: Once<ErrorHook> = Once::new();
|
||||
let hook = HOOK.get().unwrap_or_else(|| {
|
||||
DEFAULT.call_once(|| default_hook());
|
||||
DEFAULT.get().unwrap()
|
||||
});
|
||||
let hook = HOOK.get_or_init(default_hook);
|
||||
hook(error)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
pub(crate) fn capture_handler(error: &(dyn Diagnostic + 'static)) -> Box<dyn ReportHandler> {
|
||||
let hook = HOOK.call_once(default_hook);
|
||||
hook(error)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
#[cfg(feature = "std")]
|
||||
pub(crate) fn capture_handler_with_location(
|
||||
error: &(dyn Diagnostic + 'static),
|
||||
) -> Box<dyn ReportHandler> {
|
||||
static DEFAULT: Once<ErrorHook> = Once::new();
|
||||
let hook = HOOK.get().unwrap_or_else(|| {
|
||||
DEFAULT.call_once(|| default_hook());
|
||||
DEFAULT.get().unwrap()
|
||||
});
|
||||
let hook = HOOK.get_or_init(default_hook);
|
||||
let mut handler = hook(error);
|
||||
handler.track_caller(core::panic::Location::caller());
|
||||
handler
|
||||
}
|
||||
|
||||
{
|
||||
let mut handler = hook(error);
|
||||
handler.track_caller(core::panic::Location::caller());
|
||||
handler
|
||||
}
|
||||
#[track_caller]
|
||||
#[cfg(not(feature = "std"))]
|
||||
pub(crate) fn capture_handler_with_location(
|
||||
error: &(dyn Diagnostic + 'static),
|
||||
) -> Box<dyn ReportHandler> {
|
||||
let hook = HOOK.call_once(default_hook);
|
||||
let mut handler = hook(error);
|
||||
handler.track_caller(core::panic::Location::caller());
|
||||
handler
|
||||
}
|
||||
|
||||
fn get_default_printer(_err: &(dyn Diagnostic + 'static)) -> Box<dyn ReportHandler + 'static> {
|
||||
|
|
|
|||
|
|
@ -211,14 +211,14 @@ impl<C> StdError for WithSourceCode<Report, C> {
|
|||
|
||||
#[cfg(all(test, feature = "std"))]
|
||||
mod tests {
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::boxed::Box;
|
||||
#[cfg(feature = "fancy")]
|
||||
use std::format;
|
||||
use std::{
|
||||
boxed::Box,
|
||||
string::{String, ToString},
|
||||
};
|
||||
use alloc::format;
|
||||
use alloc::string::{String, ToString};
|
||||
#[cfg(feature = "fancy")]
|
||||
use std::{vec, vec::Vec};
|
||||
use alloc::{vec, vec::Vec};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::{Diagnostic, LabeledSpan, Report, SourceCode, SourceSpan};
|
||||
|
|
@ -232,7 +232,7 @@ mod tests {
|
|||
|
||||
impl Diagnostic for Inner {
|
||||
fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
|
||||
Some(Box::new(std::iter::once(LabeledSpan::underline(self.at))))
|
||||
Some(Box::new(core::iter::once(LabeledSpan::underline(self.at))))
|
||||
}
|
||||
|
||||
fn source_code(&self) -> Option<&dyn SourceCode> {
|
||||
|
|
|
|||
|
|
@ -352,25 +352,18 @@ impl MietteHandlerOpts {
|
|||
} else if let Some(force_graphical) = self.force_graphical {
|
||||
force_graphical
|
||||
} else {
|
||||
#[cfg(feature = "fancy-no-syscall")]
|
||||
#[cfg(all(feature = "fancy-no-syscall", not(feature = "fancy-no-backtrace")))]
|
||||
{
|
||||
// In no-std environment, assume graphics are available
|
||||
true
|
||||
}
|
||||
#[cfg(all(not(feature = "fancy-no-syscall"), feature = "std"))]
|
||||
#[cfg(feature = "fancy-no-backtrace")]
|
||||
{
|
||||
// In std environment, check NO_GRAPHICS env var
|
||||
if let Ok(env) = std::env::var("NO_GRAPHICS") {
|
||||
env == "0"
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
#[cfg(all(not(feature = "fancy-no-syscall"), not(feature = "std")))]
|
||||
{
|
||||
// In no-std environment without fancy-no-syscall, default to true
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -485,77 +478,63 @@ impl From<HighlighterOption> for MietteHighlighter {
|
|||
}
|
||||
|
||||
mod syscall {
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
#[inline]
|
||||
pub(super) fn terminal_width() -> Option<usize> {
|
||||
cfg_if! {
|
||||
if #[cfg(any(feature = "fancy-no-syscall", miri))] {
|
||||
None
|
||||
} else if #[cfg(feature = "fancy-no-backtrace")] {
|
||||
terminal_size::terminal_size().map(|size| size.0 .0 as usize)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
#[cfg(all(feature = "fancy-no-backtrace", not(miri)))]
|
||||
{
|
||||
terminal_size::terminal_size().map(|size| size.0 .0 as usize)
|
||||
}
|
||||
#[cfg(any(not(feature = "fancy-no-backtrace"), miri))]
|
||||
{
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn supports_hyperlinks() -> bool {
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "fancy-no-syscall")] {
|
||||
false
|
||||
} else if #[cfg(feature = "fancy-no-backtrace")] {
|
||||
supports_hyperlinks::on(supports_hyperlinks::Stream::Stderr)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
#[cfg(feature = "fancy-no-backtrace")]
|
||||
{
|
||||
supports_hyperlinks::on(supports_hyperlinks::Stream::Stderr)
|
||||
}
|
||||
#[cfg(not(feature = "fancy-no-backtrace"))]
|
||||
{
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn supports_color() -> bool {
|
||||
cfg_if! {
|
||||
if #[cfg(all(feature = "fancy", not(feature = "fancy-no-syscall")))] {
|
||||
// Standard fancy mode with full std support
|
||||
supports_color::on(supports_color::Stream::Stderr).is_some()
|
||||
} else if #[cfg(all(feature = "fancy", feature = "fancy-no-backtrace"))] {
|
||||
// Fancy mode without backtrace but with color support
|
||||
supports_color::on(supports_color::Stream::Stderr).is_some()
|
||||
} else if #[cfg(not(feature = "std"))] {
|
||||
// No-std environment - no color support by default
|
||||
false
|
||||
} else {
|
||||
// All other cases - no color support
|
||||
false
|
||||
}
|
||||
#[cfg(feature = "fancy-no-backtrace")]
|
||||
{
|
||||
supports_color::on(supports_color::Stream::Stderr).is_some()
|
||||
}
|
||||
#[cfg(not(feature = "fancy-no-backtrace"))]
|
||||
{
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn supports_color_has_16m() -> Option<bool> {
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "fancy-no-backtrace")] {
|
||||
supports_color::on(supports_color::Stream::Stderr).map(|color| color.has_16m)
|
||||
} else if #[cfg(feature = "fancy-no-syscall")] {
|
||||
// In no-std environment without color support, default to no RGB color support
|
||||
Some(false)
|
||||
} else {
|
||||
Some(true) // Fallback to assuming RGB support
|
||||
}
|
||||
#[cfg(feature = "fancy-no-backtrace")]
|
||||
{
|
||||
supports_color::on(supports_color::Stream::Stderr).map(|color| color.has_16m)
|
||||
}
|
||||
#[cfg(not(feature = "fancy-no-backtrace"))]
|
||||
{
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn supports_unicode() -> bool {
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "fancy-no-syscall")] {
|
||||
false
|
||||
} else if #[cfg(feature = "fancy-no-backtrace")] {
|
||||
supports_unicode::on(supports_unicode::Stream::Stderr)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
#[cfg(feature = "fancy-no-backtrace")]
|
||||
{
|
||||
supports_unicode::on(supports_unicode::Stream::Stderr)
|
||||
}
|
||||
#[cfg(not(feature = "fancy-no-backtrace"))]
|
||||
{
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,13 +71,9 @@ impl GraphicalTheme {
|
|||
|
||||
impl Default for GraphicalTheme {
|
||||
fn default() -> Self {
|
||||
#[cfg(feature = "fancy-no-syscall")]
|
||||
{
|
||||
// In no-std environments, default to no-color mode
|
||||
Self::unicode_nocolor()
|
||||
}
|
||||
#[cfg(all(not(feature = "fancy-no-syscall"), feature = "std"))]
|
||||
#[cfg(feature = "fancy-no-backtrace")]
|
||||
{
|
||||
use std::io::IsTerminal;
|
||||
match std::env::var("NO_COLOR") {
|
||||
_ if !std::io::stdout().is_terminal() || !std::io::stderr().is_terminal() => {
|
||||
Self::none()
|
||||
|
|
@ -86,10 +82,9 @@ impl Default for GraphicalTheme {
|
|||
_ => Self::unicode(),
|
||||
}
|
||||
}
|
||||
#[cfg(all(not(feature = "fancy-no-syscall"), not(feature = "std")))]
|
||||
#[cfg(not(feature = "fancy-no-backtrace"))]
|
||||
{
|
||||
// In no-std environment, default to unicode theme
|
||||
Self::unicode()
|
||||
Self::unicode_nocolor()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,23 +84,17 @@ impl MietteHighlighter {
|
|||
|
||||
impl Default for MietteHighlighter {
|
||||
fn default() -> Self {
|
||||
#[cfg(all(feature = "syntect-highlighter", not(feature = "fancy-no-syscall")))]
|
||||
#[cfg(feature = "syntect-highlighter")]
|
||||
{
|
||||
use std::io::IsTerminal;
|
||||
match std::env::var("NO_COLOR") {
|
||||
_ if !std::io::stdout().is_terminal() || !std::io::stderr().is_terminal() => {
|
||||
//TODO: should use ANSI styling instead of 24-bit truecolor here
|
||||
Self(Arc::new(SyntectHighlighter::default()))
|
||||
}
|
||||
Ok(string) if string != "0" => MietteHighlighter::nocolor(),
|
||||
_ => Self(Arc::new(SyntectHighlighter::default())),
|
||||
}
|
||||
}
|
||||
#[cfg(all(feature = "syntect-highlighter", feature = "fancy-no-syscall"))]
|
||||
{
|
||||
// In no-std environment, use syntect but without terminal detection
|
||||
Self(Arc::new(SyntectHighlighter::default()))
|
||||
}
|
||||
#[cfg(not(feature = "syntect-highlighter"))]
|
||||
{
|
||||
MietteHighlighter::nocolor()
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ impl SyntectHighlighter {
|
|||
}
|
||||
// finally, attempt to guess syntax based on first line
|
||||
self.syntax_set.find_syntax_by_first_line(
|
||||
std::str::from_utf8(contents.data())
|
||||
core::str::from_utf8(contents.data())
|
||||
.ok()?
|
||||
.split('\n')
|
||||
.next()?,
|
||||
|
|
|
|||
22
src/lib.rs
22
src/lib.rs
|
|
@ -1,6 +1,11 @@
|
|||
#![no_std]
|
||||
#![deny(missing_docs, missing_debug_implementations, nonstandard_style)]
|
||||
#![warn(unreachable_pub, rust_2018_idioms)]
|
||||
#![warn(
|
||||
clippy::alloc_instead_of_core,
|
||||
clippy::std_instead_of_core,
|
||||
clippy::std_instead_of_alloc
|
||||
)]
|
||||
#![allow(unexpected_cfgs)]
|
||||
|
||||
//! You run miette? You run her code like the software? Oh. Oh! Error code for
|
||||
|
|
@ -845,18 +850,13 @@
|
|||
#[cfg(feature = "std")]
|
||||
extern crate std;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::error::Error as StdError;
|
||||
pub use core::error::Error as StdError;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
/// Compatibility trait for error handling in no_std environments.
|
||||
/// This trait provides a subset of `std::error::Error` functionality
|
||||
/// suitable for no_std environments.
|
||||
pub trait StdError: core::fmt::Debug + core::fmt::Display {
|
||||
/// Returns the lower-level source of this error, if any.
|
||||
fn source(&self) -> Option<&(dyn StdError + 'static)> {
|
||||
None
|
||||
}
|
||||
#[doc(hidden)]
|
||||
pub mod __alloc {
|
||||
extern crate alloc;
|
||||
pub use alloc::borrow;
|
||||
pub use alloc::boxed::Box;
|
||||
}
|
||||
|
||||
#[cfg(feature = "derive")]
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
extern crate alloc;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use crate::StdError as Error;
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use core::error::Error;
|
||||
use core::fmt::{Debug, Display};
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
|
@ -267,6 +264,7 @@ impl MietteDiagnostic {
|
|||
#[cfg(feature = "serde")]
|
||||
#[test]
|
||||
fn test_serialize_miette_diagnostic() {
|
||||
use alloc::format;
|
||||
use serde_json::json;
|
||||
|
||||
use crate::diagnostic;
|
||||
|
|
@ -317,6 +315,7 @@ fn test_serialize_miette_diagnostic() {
|
|||
#[cfg(feature = "serde")]
|
||||
#[test]
|
||||
fn test_deserialize_miette_diagnostic() {
|
||||
use alloc::format;
|
||||
use serde_json::json;
|
||||
|
||||
use crate::diagnostic;
|
||||
|
|
|
|||
27
src/panic.rs
27
src/panic.rs
|
|
@ -1,6 +1,11 @@
|
|||
#[cfg(feature = "std")]
|
||||
// `fancy` feature requires std, so std imports are fine here.
|
||||
#![allow(
|
||||
clippy::std_instead_of_core,
|
||||
clippy::std_instead_of_alloc,
|
||||
clippy::alloc_instead_of_core
|
||||
)]
|
||||
|
||||
use std::boxed::Box;
|
||||
#[cfg(feature = "std")]
|
||||
use std::{
|
||||
eprintln,
|
||||
error::Error,
|
||||
|
|
@ -9,14 +14,11 @@ use std::{
|
|||
string::{String, ToString},
|
||||
};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use backtrace::Backtrace;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use crate::{Context, Diagnostic, Result};
|
||||
|
||||
/// Makes miette show pretty error messages when your program crashes.
|
||||
#[cfg(feature = "std")]
|
||||
pub fn set_panic_hook() {
|
||||
std::panic::set_hook(Box::new(move |info| {
|
||||
let mut message = "Something went wrong".to_string();
|
||||
|
|
@ -38,20 +40,9 @@ pub fn set_panic_hook() {
|
|||
}));
|
||||
}
|
||||
|
||||
/// Makes miette show pretty error messages when your program crashes.
|
||||
///
|
||||
/// On computers without the standard library, this function does nothing
|
||||
/// because crash hooks need the standard library to work.
|
||||
#[cfg(not(feature = "std"))]
|
||||
pub fn set_panic_hook() {
|
||||
// Does nothing on computers without the standard library
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cfg(feature = "std")]
|
||||
struct Panic(String);
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Display for Panic {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let msg = &self.0;
|
||||
|
|
@ -60,10 +51,8 @@ impl Display for Panic {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Error for Panic {}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Diagnostic for Panic {
|
||||
fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
|
||||
Some(Box::new(
|
||||
|
|
@ -72,7 +61,6 @@ impl Diagnostic for Panic {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Panic {
|
||||
fn backtrace() -> String {
|
||||
use std::fmt::Write;
|
||||
|
|
@ -129,7 +117,6 @@ impl Panic {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(feature = "std")]
|
||||
mod tests {
|
||||
use std::{borrow::ToOwned, error::Error};
|
||||
|
||||
|
|
|
|||
|
|
@ -177,8 +177,8 @@ impl From<String> for Box<dyn Diagnostic + Send + Sync> {
|
|||
use crate::DiagnosticError;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl From<Box<dyn std::error::Error + Send + Sync>> for Box<dyn Diagnostic + Send + Sync> {
|
||||
fn from(s: Box<dyn std::error::Error + Send + Sync>) -> Self {
|
||||
impl From<Box<dyn core::error::Error + Send + Sync>> for Box<dyn Diagnostic + Send + Sync> {
|
||||
fn from(s: Box<dyn core::error::Error + Send + Sync>) -> Self {
|
||||
Box::new(DiagnosticError(s))
|
||||
}
|
||||
}
|
||||
|
|
@ -374,6 +374,7 @@ impl LabeledSpan {
|
|||
#[cfg(feature = "serde")]
|
||||
#[test]
|
||||
fn test_serialize_labeled_span() {
|
||||
use alloc::string::ToString;
|
||||
use serde_json::json;
|
||||
|
||||
assert_eq!(
|
||||
|
|
@ -397,6 +398,7 @@ fn test_serialize_labeled_span() {
|
|||
#[cfg(feature = "serde")]
|
||||
#[test]
|
||||
fn test_deserialize_labeled_span() {
|
||||
use alloc::string::ToString;
|
||||
use serde_json::json;
|
||||
|
||||
let span: LabeledSpan = serde_json::from_value(json!({
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
#![cfg(feature = "fancy-no-backtrace")]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use miette::{Diagnostic, MietteHandler, MietteHandlerOpts, ReportHandler, RgbColors};
|
||||
use regex::Regex;
|
||||
use std::ffi::OsString;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#[allow(unused_assignments)] // some fields unused when feature="fancy"
|
||||
extern crate alloc;
|
||||
#![allow(unused_assignments)] // some fields unused when feature="fancy"
|
||||
|
||||
use miette::{Diagnostic, Report, Severity, SourceSpan};
|
||||
use thiserror::Error;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
#![cfg(feature = "fancy-no-backtrace")]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use miette::{
|
||||
Diagnostic, GraphicalReportHandler, GraphicalTheme, MietteError, NamedSource,
|
||||
NarratableReportHandler, Report, SourceSpan,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
#![cfg(feature = "fancy-no-backtrace")]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use miette::{Diagnostic, MietteError, NamedSource, NarratableReportHandler, Report, SourceSpan};
|
||||
|
||||
use miette::{GraphicalReportHandler, GraphicalTheme};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
// Testing of the `diagnostic` attr used by derive(Diagnostic)
|
||||
extern crate alloc;
|
||||
|
||||
use miette::{Diagnostic, LabeledSpan, NamedSource, SourceSpan};
|
||||
use thiserror::Error;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
extern crate alloc;
|
||||
|
||||
use std::{
|
||||
collections::{LinkedList, VecDeque},
|
||||
ops::Range,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
extern crate alloc;
|
||||
|
||||
use miette::Diagnostic;
|
||||
|
||||
#[derive(Debug, miette::Diagnostic, thiserror::Error)]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
mod json_report_handler {
|
||||
extern crate alloc;
|
||||
|
||||
use miette::{Diagnostic, MietteError, NamedSource, Report, SourceSpan};
|
||||
|
||||
use miette::JSONReportHandler;
|
||||
|
|
|
|||
Loading…
Reference in New Issue