mirror of https://github.com/zkat/miette.git
fix: address review comments
- Fixed compilation errors in no-std mode (TestError Debug derive, ToString imports) - Addressed consistency issues: Option qualification, StdError naming, Borrow impl - Fixed feature flag logic for supports_color function with proper priority ordering - Added conditional compilation for std-dependent features in panic.rs, handler.rs, theme.rs - Made syntect-highlighter feature explicitly require std - Consolidated duplicate Borrow implementations using core::borrow::Borrow
This commit is contained in:
parent
18c217f0dc
commit
359941fdef
|
|
@ -65,7 +65,7 @@ fancy-no-backtrace = [
|
||||||
"dep:supports-unicode",
|
"dep:supports-unicode",
|
||||||
]
|
]
|
||||||
fancy = ["fancy-no-backtrace", "dep:backtrace", "dep:backtrace-ext"]
|
fancy = ["fancy-no-backtrace", "dep:backtrace", "dep:backtrace-ext"]
|
||||||
syntect-highlighter = ["fancy-no-backtrace", "dep:syntect"]
|
syntect-highlighter = ["fancy-no-backtrace", "dep:syntect", "std"]
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["miette-derive"]
|
members = ["miette-derive"]
|
||||||
|
|
|
||||||
17
README.md
17
README.md
|
|
@ -58,8 +58,8 @@ diagnostic error code: ruget::api::bad_json
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
- Generic [`Diagnostic`] protocol, compatible (and dependent on)
|
- Generic [`Diagnostic`] protocol, compatible with `std::error::Error`.
|
||||||
[`std::error::Error`].
|
Works without the standard library: Just turn off the default `std` feature and you can use `miette` in places like embedded systems or web browsers that don't have the full standard library. You still need `alloc` for memory management.
|
||||||
- Unique error codes on every [`Diagnostic`].
|
- Unique error codes on every [`Diagnostic`].
|
||||||
- Custom links to get more details on error codes.
|
- Custom links to get more details on error codes.
|
||||||
- Super handy derive macro for defining diagnostic metadata.
|
- Super handy derive macro for defining diagnostic metadata.
|
||||||
|
|
@ -93,6 +93,19 @@ If you want to use the fancy printer in all these screenshots:
|
||||||
$ cargo add miette --features fancy
|
$ cargo add miette --features fancy
|
||||||
```
|
```
|
||||||
|
|
||||||
|
For computers without the standard library (like microcontrollers or web browsers):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ cargo add miette --no-default-features --features derive
|
||||||
|
```
|
||||||
|
|
||||||
|
Available features you can turn on or off:
|
||||||
|
- `std` (on by default): Use the standard library
|
||||||
|
- `derive`: Lets you automatically create error types
|
||||||
|
- `fancy`: Shows pretty error messages with colors
|
||||||
|
- `fancy-no-syscall`: Pretty errors without using system calls
|
||||||
|
- `fancy-no-backtrace`: Pretty errors without showing the call stack
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
|
|
||||||
8
build.rs
8
build.rs
|
|
@ -5,12 +5,8 @@ fn main() {
|
||||||
println!("cargo:rustc-cfg=nightly")
|
println!("cargo:rustc-cfg=nightly")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure track_caller based on Rust version
|
// track_caller is stable since Rust 1.46 (2020), so no version check needed
|
||||||
if let Ok(version) = rustc_version::version() {
|
println!("cargo:rustc-cfg=track_caller");
|
||||||
if version >= rustc_version::Version::new(1, 46, 0) {
|
|
||||||
println!("cargo:rustc-cfg=track_caller");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add check-cfg for conditional configurations
|
// Add check-cfg for conditional configurations
|
||||||
println!("cargo:rustc-check-cfg=cfg(doc_cfg)");
|
println!("cargo:rustc-check-cfg=cfg(doc_cfg)");
|
||||||
|
|
|
||||||
|
|
@ -56,13 +56,13 @@ impl Code {
|
||||||
let code = &code.as_ref()?.0;
|
let code = &code.as_ref()?.0;
|
||||||
Some(match fields {
|
Some(match fields {
|
||||||
syn::Fields::Named(_) => {
|
syn::Fields::Named(_) => {
|
||||||
quote! { Self::#ident { .. } => Option::Some(alloc::boxed::Box::new(#code)), }
|
quote! { Self::#ident { .. } => core::option::Option::Some(alloc::boxed::Box::new(#code)), }
|
||||||
}
|
}
|
||||||
syn::Fields::Unnamed(_) => {
|
syn::Fields::Unnamed(_) => {
|
||||||
quote! { Self::#ident(..) => Option::Some(alloc::boxed::Box::new(#code)), }
|
quote! { Self::#ident(..) => core::option::Option::Some(alloc::boxed::Box::new(#code)), }
|
||||||
}
|
}
|
||||||
syn::Fields::Unit => {
|
syn::Fields::Unit => {
|
||||||
quote! { Self::#ident => Option::Some(alloc::boxed::Box::new(#code)), }
|
quote! { Self::#ident => core::option::Option::Some(alloc::boxed::Box::new(#code)), }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
@ -72,8 +72,8 @@ impl Code {
|
||||||
pub(crate) fn gen_struct(&self) -> Option<TokenStream> {
|
pub(crate) fn gen_struct(&self) -> Option<TokenStream> {
|
||||||
let code = &self.0;
|
let code = &self.0;
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
fn code(&self) -> Option<alloc::boxed::Box<dyn core::fmt::Display + '_>> {
|
fn code(&self) -> core::option::Option<alloc::boxed::Box<dyn core::fmt::Display + '_>> {
|
||||||
Some(alloc::boxed::Box::new(#code))
|
core::option::Option::Some(alloc::boxed::Box::new(#code))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ impl DiagnosticSource {
|
||||||
};
|
};
|
||||||
quote! {
|
quote! {
|
||||||
Self::#ident #display_pat => {
|
Self::#ident #display_pat => {
|
||||||
Some(alloc::borrow::Borrow::borrow(#rel))
|
core::option::Option::Some(alloc::borrow::Borrow::borrow(#rel))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -70,8 +70,8 @@ impl DiagnosticSource {
|
||||||
pub(crate) fn gen_struct(&self) -> Option<TokenStream> {
|
pub(crate) fn gen_struct(&self) -> Option<TokenStream> {
|
||||||
let rel = &self.0;
|
let rel = &self.0;
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
fn diagnostic_source<'a>(&'a self) -> Option<&'a dyn miette::Diagnostic> {
|
fn diagnostic_source<'a>(&'a self) -> core::option::Option<&'a dyn miette::Diagnostic> {
|
||||||
Some(alloc::borrow::Borrow::borrow(&self.#rel))
|
core::option::Option::Some(alloc::borrow::Borrow::borrow(&self.#rel))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,9 @@ impl Diagnostic for MietteError {
|
||||||
pub(crate) mod tests {
|
pub(crate) mod tests {
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
use crate::StdError as Error;
|
use crate::StdError as Error;
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
use alloc::string::ToString;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::string::ToString;
|
use std::string::ToString;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
@ -101,6 +104,7 @@ pub(crate) mod tests {
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub(crate) struct TestError(pub(crate) io::Error);
|
pub(crate) struct TestError(pub(crate) io::Error);
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
|
#[derive(Debug)]
|
||||||
pub(crate) struct TestError(pub(crate) &'static str);
|
pub(crate) struct TestError(pub(crate) &'static str);
|
||||||
|
|
||||||
impl Display for TestError {
|
impl Display for TestError {
|
||||||
|
|
|
||||||
|
|
@ -817,14 +817,6 @@ impl AsRef<dyn StdError> for Report {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
impl std::borrow::Borrow<dyn Diagnostic> for Report {
|
|
||||||
fn borrow(&self) -> &(dyn Diagnostic + 'static) {
|
|
||||||
self.as_ref()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
|
||||||
impl core::borrow::Borrow<dyn Diagnostic> for Report {
|
impl core::borrow::Borrow<dyn Diagnostic> for Report {
|
||||||
fn borrow(&self) -> &(dyn Diagnostic + 'static) {
|
fn borrow(&self) -> &(dyn Diagnostic + 'static) {
|
||||||
self.as_ref()
|
self.as_ref()
|
||||||
|
|
|
||||||
|
|
@ -60,13 +60,12 @@ impl<T, E: Error + Send + Sync + 'static> IntoDiagnostic<T, E> for Result<T, E>
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use super::IntoDiagnostic;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::io::{self};
|
use std::io::{self};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::string::ToString;
|
use std::string::ToString;
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use crate::error::tests::TestError;
|
use crate::error::tests::TestError;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -357,7 +357,7 @@ impl MietteHandlerOpts {
|
||||||
// In no-std environment, assume graphics are available
|
// In no-std environment, assume graphics are available
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "fancy-no-syscall"))]
|
#[cfg(all(not(feature = "fancy-no-syscall"), feature = "std"))]
|
||||||
{
|
{
|
||||||
// In std environment, check NO_GRAPHICS env var
|
// In std environment, check NO_GRAPHICS env var
|
||||||
if let Ok(env) = std::env::var("NO_GRAPHICS") {
|
if let Ok(env) = std::env::var("NO_GRAPHICS") {
|
||||||
|
|
@ -366,6 +366,11 @@ impl MietteHandlerOpts {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(all(not(feature = "fancy-no-syscall"), not(feature = "std")))]
|
||||||
|
{
|
||||||
|
// In no-std environment without fancy-no-syscall, default to true
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -487,8 +492,10 @@ mod syscall {
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(any(feature = "fancy-no-syscall", miri))] {
|
if #[cfg(any(feature = "fancy-no-syscall", miri))] {
|
||||||
None
|
None
|
||||||
} else {
|
} else if #[cfg(feature = "fancy-no-backtrace")] {
|
||||||
terminal_size::terminal_size().map(|size| size.0 .0 as usize)
|
terminal_size::terminal_size().map(|size| size.0 .0 as usize)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -498,8 +505,10 @@ mod syscall {
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(feature = "fancy-no-syscall")] {
|
if #[cfg(feature = "fancy-no-syscall")] {
|
||||||
false
|
false
|
||||||
} else {
|
} else if #[cfg(feature = "fancy-no-backtrace")] {
|
||||||
supports_hyperlinks::on(supports_hyperlinks::Stream::Stderr)
|
supports_hyperlinks::on(supports_hyperlinks::Stream::Stderr)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -507,13 +516,18 @@ mod syscall {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) fn supports_color() -> bool {
|
pub(super) fn supports_color() -> bool {
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(feature = "fancy-no-backtrace")] {
|
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()
|
supports_color::on(supports_color::Stream::Stderr).is_some()
|
||||||
} else if #[cfg(feature = "fancy-no-syscall")] {
|
} else if #[cfg(all(feature = "fancy", feature = "fancy-no-backtrace"))] {
|
||||||
// In no-std environment without color support, default to no color support
|
// 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
|
false
|
||||||
} else {
|
} else {
|
||||||
true // Fallback to assuming color support
|
// All other cases - no color support
|
||||||
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -537,8 +551,10 @@ mod syscall {
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(feature = "fancy-no-syscall")] {
|
if #[cfg(feature = "fancy-no-syscall")] {
|
||||||
false
|
false
|
||||||
} else {
|
} else if #[cfg(feature = "fancy-no-backtrace")] {
|
||||||
supports_unicode::on(supports_unicode::Stream::Stderr)
|
supports_unicode::on(supports_unicode::Stream::Stderr)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ impl Default for GraphicalTheme {
|
||||||
// In no-std environments, default to no-color mode
|
// In no-std environments, default to no-color mode
|
||||||
Self::unicode_nocolor()
|
Self::unicode_nocolor()
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "fancy-no-syscall"))]
|
#[cfg(all(not(feature = "fancy-no-syscall"), feature = "std"))]
|
||||||
{
|
{
|
||||||
match std::env::var("NO_COLOR") {
|
match std::env::var("NO_COLOR") {
|
||||||
_ if !std::io::stdout().is_terminal() || !std::io::stderr().is_terminal() => {
|
_ if !std::io::stdout().is_terminal() || !std::io::stderr().is_terminal() => {
|
||||||
|
|
@ -86,6 +86,11 @@ impl Default for GraphicalTheme {
|
||||||
_ => Self::unicode(),
|
_ => Self::unicode(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(all(not(feature = "fancy-no-syscall"), not(feature = "std")))]
|
||||||
|
{
|
||||||
|
// In no-std environment, default to unicode theme
|
||||||
|
Self::unicode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use core::str;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
|
||||||
21
src/lib.rs
21
src/lib.rs
|
|
@ -60,8 +60,8 @@
|
||||||
//!
|
//!
|
||||||
//! ## Features
|
//! ## Features
|
||||||
//!
|
//!
|
||||||
//! - Generic [`Diagnostic`] protocol, compatible (and dependent on)
|
//! - Generic [`Diagnostic`] protocol, compatible with `std::error::Error`.
|
||||||
//! [`std::error::Error`].
|
//! Works without the standard library: Just turn off the default `std` feature and you can use `miette` in places like embedded systems or web browsers that don't have the full standard library. You still need `alloc` for memory management.
|
||||||
//! - Unique error codes on every [`Diagnostic`].
|
//! - Unique error codes on every [`Diagnostic`].
|
||||||
//! - Custom links to get more details on error codes.
|
//! - Custom links to get more details on error codes.
|
||||||
//! - Super handy derive macro for defining diagnostic metadata.
|
//! - Super handy derive macro for defining diagnostic metadata.
|
||||||
|
|
@ -95,6 +95,19 @@
|
||||||
//! $ cargo add miette --features fancy
|
//! $ cargo add miette --features fancy
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
//! For computers without the standard library (like microcontrollers or web browsers):
|
||||||
|
//!
|
||||||
|
//! ```sh
|
||||||
|
//! $ cargo add miette --no-default-features --features derive
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! Available features you can turn on or off:
|
||||||
|
//! - `std` (on by default): Use the standard library
|
||||||
|
//! - `derive`: Lets you automatically create error types
|
||||||
|
//! - `fancy`: Shows pretty error messages with colors
|
||||||
|
//! - `fancy-no-syscall`: Pretty errors without using system calls
|
||||||
|
//! - `fancy-no-backtrace`: Pretty errors without showing the call stack
|
||||||
|
//!
|
||||||
//! ## Example
|
//! ## Example
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
|
|
@ -829,10 +842,6 @@
|
||||||
//! under the Apache License. Some code is taken from
|
//! under the Apache License. Some code is taken from
|
||||||
//! [`ariadne`](https://github.com/zesterer/ariadne), which is MIT licensed.
|
//! [`ariadne`](https://github.com/zesterer/ariadne), which is MIT licensed.
|
||||||
|
|
||||||
// For doctests that use Diagnostic derive macro
|
|
||||||
#[cfg(test)]
|
|
||||||
extern crate alloc;
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
extern crate std;
|
extern crate std;
|
||||||
|
|
||||||
|
|
|
||||||
22
src/panic.rs
22
src/panic.rs
|
|
@ -1,4 +1,6 @@
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::boxed::Box;
|
use std::boxed::Box;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use std::{
|
use std::{
|
||||||
eprintln,
|
eprintln,
|
||||||
error::Error,
|
error::Error,
|
||||||
|
|
@ -7,11 +9,14 @@ use std::{
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use backtrace::Backtrace;
|
use backtrace::Backtrace;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use crate::{Context, Diagnostic, Result};
|
use crate::{Context, Diagnostic, Result};
|
||||||
|
|
||||||
/// Tells miette to render panics using its rendering engine.
|
/// Makes miette show pretty error messages when your program crashes.
|
||||||
|
#[cfg(feature = "std")]
|
||||||
pub fn set_panic_hook() {
|
pub fn set_panic_hook() {
|
||||||
std::panic::set_hook(Box::new(move |info| {
|
std::panic::set_hook(Box::new(move |info| {
|
||||||
let mut message = "Something went wrong".to_string();
|
let mut message = "Something went wrong".to_string();
|
||||||
|
|
@ -33,9 +38,20 @@ 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)]
|
#[derive(Debug)]
|
||||||
|
#[cfg(feature = "std")]
|
||||||
struct Panic(String);
|
struct Panic(String);
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Display for Panic {
|
impl Display for Panic {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let msg = &self.0;
|
let msg = &self.0;
|
||||||
|
|
@ -44,8 +60,10 @@ impl Display for Panic {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Error for Panic {}
|
impl Error for Panic {}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Diagnostic for Panic {
|
impl Diagnostic for Panic {
|
||||||
fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
|
fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
|
||||||
Some(Box::new(
|
Some(Box::new(
|
||||||
|
|
@ -54,6 +72,7 @@ impl Diagnostic for Panic {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
impl Panic {
|
impl Panic {
|
||||||
fn backtrace() -> String {
|
fn backtrace() -> String {
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
@ -110,6 +129,7 @@ impl Panic {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[cfg(feature = "std")]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::{borrow::ToOwned, error::Error};
|
use std::{borrow::ToOwned, error::Error};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue