Skip to content

Commit

Permalink
feat(serde): Add serde support (#264)
Browse files Browse the repository at this point in the history
Fixes: #260
  • Loading branch information
gavrilikhin-d authored May 14, 2023
1 parent 024145d commit c25676c
Show file tree
Hide file tree
Showing 4 changed files with 251 additions and 23 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ supports-unicode = { version = "2.0.0", optional = true }
backtrace = { version = "0.3.61", optional = true }
terminal_size = { version = "0.1.17", optional = true }
backtrace-ext = { version = "0.2.1", optional = true }
serde = { version = "1.0.162", features = ["derive"], optional = true }

[dev-dependencies]
semver = "1.0.4"
Expand All @@ -40,6 +41,8 @@ syn = { version = "2.0", features = ["full"] }
regex = "1.5"
lazy_static = "1.4"

serde_json = "1.0.64"

[features]
default = []
no-format-args-capture = []
Expand Down
5 changes: 4 additions & 1 deletion src/eyreish/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,10 @@ macro_rules! miette {
/// ```
#[macro_export]
macro_rules! diagnostic {
($($key:ident = $value:expr,)* $fmt:literal $($arg:tt)*) => {{
($fmt:literal $($arg:tt)*) => {{
$crate::MietteDiagnostic::new(format!($fmt $($arg)*))
}};
($($key:ident = $value:expr,)+ $fmt:literal $($arg:tt)*) => {{
let mut diag = $crate::MietteDiagnostic::new(format!($fmt $($arg)*));
$(diag.$key = Some($value.into());)*
diag
Expand Down
115 changes: 115 additions & 0 deletions src/miette_diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ use std::{
fmt::{Debug, Display},
};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use crate::{Diagnostic, LabeledSpan, Severity};

/// Diagnostic that can be created at runtime.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct MietteDiagnostic {
/// Displayed diagnostic message
pub message: String,
Expand All @@ -15,17 +19,22 @@ pub struct MietteDiagnostic {
/// in the toplevel crate's documentation for easy searching.
/// Rust path format (`foo::bar::baz`) is recommended, but more classic
/// codes like `E0123` will work just fine
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub code: Option<String>,
/// [`Diagnostic`] severity. Intended to be used by
/// [`ReportHandler`](crate::ReportHandler)s to change the way different
/// [`Diagnostic`]s are displayed. Defaults to [`Severity::Error`]
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub severity: Option<Severity>,
/// Additional help text related to this Diagnostic
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub help: Option<String>,
/// URL to visit for a more detailed explanation/help about this
/// [`Diagnostic`].
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub url: Option<String>,
/// Labels to apply to this `Diagnostic`'s [`Diagnostic::source_code`]
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub labels: Option<Vec<LabeledSpan>>,
}

Expand Down Expand Up @@ -248,3 +257,109 @@ impl MietteDiagnostic {
self
}
}

#[cfg(feature = "serde")]
#[test]
fn test_serialize_miette_diagnostic() {
use serde_json::json;

use crate::diagnostic;

let diag = diagnostic!("message");
let json = json!({ "message": "message" });
assert_eq!(json!(diag), json);

let diag = diagnostic!(
code = "code",
help = "help",
url = "url",
labels = [
LabeledSpan::at_offset(0, "label1"),
LabeledSpan::at(1..3, "label2")
],
severity = Severity::Warning,
"message"
);
let json = json!({
"message": "message",
"code": "code",
"help": "help",
"url": "url",
"severity": "Warning",
"labels": [
{
"span": {
"offset": 0,
"length": 0
},
"label": "label1"
},
{
"span": {
"offset": 1,
"length": 2
},
"label": "label2"
}
]
});
assert_eq!(json!(diag), json);
}

#[cfg(feature = "serde")]
#[test]
fn test_deserialize_miette_diagnostic() {
use serde_json::json;

use crate::diagnostic;

let json = json!({ "message": "message" });
let diag = diagnostic!("message");
assert_eq!(diag, serde_json::from_value(json).unwrap());

let json = json!({
"message": "message",
"help": null,
"code": null,
"severity": null,
"url": null,
"labels": null
});
assert_eq!(diag, serde_json::from_value(json).unwrap());

let diag = diagnostic!(
code = "code",
help = "help",
url = "url",
labels = [
LabeledSpan::at_offset(0, "label1"),
LabeledSpan::at(1..3, "label2")
],
severity = Severity::Warning,
"message"
);
let json = json!({
"message": "message",
"code": "code",
"help": "help",
"url": "url",
"severity": "Warning",
"labels": [
{
"span": {
"offset": 0,
"length": 0
},
"label": "label1"
},
{
"span": {
"offset": 1,
"length": 2
},
"label": "label2"
}
]
});
assert_eq!(diag, serde_json::from_value(json).unwrap());
}
Loading

0 comments on commit c25676c

Please sign in to comment.