mirror of https://github.com/zkat/miette.git
fix(json): proper escapes for JSON strings (#101)
Includes two fixes: 1. Things like `\n` are not doubly-escaped any more 2. The backslash `\` itself in the source is escaped
This commit is contained in:
parent
52e5ec8064
commit
645ef6a1b6
|
|
@ -1,4 +1,4 @@
|
||||||
use std::fmt;
|
use std::fmt::{self, Write};
|
||||||
|
|
||||||
use crate::{protocol::Diagnostic, ReportHandler, Severity};
|
use crate::{protocol::Diagnostic, ReportHandler, Severity};
|
||||||
|
|
||||||
|
|
@ -23,20 +23,34 @@ impl Default for JSONReportHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn escape(input: &str) -> String {
|
struct Escape<'a>(&'a str);
|
||||||
input
|
|
||||||
.chars()
|
impl fmt::Display for Escape<'_> {
|
||||||
.map(|c| match c {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
'"' => "\\\\\"".to_string(),
|
for c in self.0.chars() {
|
||||||
'\'' => "\\\\'".to_string(),
|
let escape = match c {
|
||||||
'\r' => "\\\\r".to_string(),
|
'\\' => Some(r"\\"),
|
||||||
'\n' => "\\\\n".to_string(),
|
'"' => Some(r#"\""#),
|
||||||
'\t' => "\\\\t".to_string(),
|
'\'' => Some(r"\'"),
|
||||||
'\u{08}' => "\\\\b".to_string(),
|
'\r' => Some(r"\r"),
|
||||||
'\u{0c}' => "\\\\f".to_string(),
|
'\n' => Some(r"\n"),
|
||||||
c => format!("{}", c),
|
'\t' => Some(r"\t"),
|
||||||
})
|
'\u{08}' => Some(r"\b"),
|
||||||
.collect()
|
'\u{0c}' => Some(r"\f"),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
if let Some(escape) = escape {
|
||||||
|
f.write_str(escape)?;
|
||||||
|
} else {
|
||||||
|
f.write_char(c)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn escape(input: &'_ str) -> Escape<'_> {
|
||||||
|
Escape(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JSONReportHandler {
|
impl JSONReportHandler {
|
||||||
|
|
@ -93,7 +107,13 @@ impl JSONReportHandler {
|
||||||
}
|
}
|
||||||
if let Some(relateds) = diagnostic.related() {
|
if let Some(relateds) = diagnostic.related() {
|
||||||
write!(f, r#""related": ["#)?;
|
write!(f, r#""related": ["#)?;
|
||||||
|
let mut add_comma = false;
|
||||||
for related in relateds {
|
for related in relateds {
|
||||||
|
if add_comma {
|
||||||
|
write!(f, ",")?;
|
||||||
|
} else {
|
||||||
|
add_comma = true;
|
||||||
|
}
|
||||||
self.render_report(f, related)?;
|
self.render_report(f, related)?;
|
||||||
}
|
}
|
||||||
write!(f, "]")?;
|
write!(f, "]")?;
|
||||||
|
|
@ -127,3 +147,9 @@ impl ReportHandler for JSONReportHandler {
|
||||||
self.render_report(f, diagnostic)
|
self.render_report(f, diagnostic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_escape() {
|
||||||
|
assert_eq!(escape("a\nb").to_string(), r"a\nb");
|
||||||
|
assert_eq!(escape("C:\\Miette").to_string(), r"C:\\Miette");
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -497,7 +497,7 @@ mod json_report_handler {
|
||||||
println!("Error: {}", out);
|
println!("Error: {}", out);
|
||||||
let expected: String = r#"
|
let expected: String = r#"
|
||||||
{
|
{
|
||||||
"message": "wtf?!\\nit broke :(",
|
"message": "wtf?!\nit broke :(",
|
||||||
"code": "oops::my::bad",
|
"code": "oops::my::bad",
|
||||||
"severity": "error",
|
"severity": "error",
|
||||||
"help": "try doing it better next time?",
|
"help": "try doing it better next time?",
|
||||||
|
|
@ -737,11 +737,18 @@ mod json_report_handler {
|
||||||
let err = MyBad {
|
let err = MyBad {
|
||||||
src: NamedSource::new("bad_file.rs", src.clone()),
|
src: NamedSource::new("bad_file.rs", src.clone()),
|
||||||
highlight: (9, 4).into(),
|
highlight: (9, 4).into(),
|
||||||
related: vec![MyBad {
|
related: vec![
|
||||||
src: NamedSource::new("bad_file2.rs", src),
|
MyBad {
|
||||||
highlight: (0, 6).into(),
|
src: NamedSource::new("bad_file2.rs", src.clone()),
|
||||||
related: vec![],
|
highlight: (0, 6).into(),
|
||||||
}],
|
related: vec![],
|
||||||
|
},
|
||||||
|
MyBad {
|
||||||
|
src: NamedSource::new("bad_file3.rs", src),
|
||||||
|
highlight: (0, 6).into(),
|
||||||
|
related: vec![],
|
||||||
|
},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
let out = fmt_report(err.into());
|
let out = fmt_report(err.into());
|
||||||
println!("Error: {}", out);
|
println!("Error: {}", out);
|
||||||
|
|
@ -777,6 +784,22 @@ mod json_report_handler {
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"related": []
|
"related": []
|
||||||
|
},{
|
||||||
|
"message": "oops!",
|
||||||
|
"code": "oops::my::bad",
|
||||||
|
"severity": "error",
|
||||||
|
"help": "try doing it better next time?",
|
||||||
|
"filename": "bad_file3.rs",
|
||||||
|
"labels": [
|
||||||
|
{
|
||||||
|
"label": "this bit here",
|
||||||
|
"span": {
|
||||||
|
"offset": 0,
|
||||||
|
"length": 6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"related": []
|
||||||
}]
|
}]
|
||||||
}"#
|
}"#
|
||||||
.lines()
|
.lines()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue