Skip to content

Commit d7b5ea5

Browse files
committed
Improve error reporting some more #3
1 parent bb5ffdd commit d7b5ea5

File tree

4 files changed

+43
-30
lines changed

4 files changed

+43
-30
lines changed

sqlsonnet-cli/src/sqlsonnet.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,8 @@ async fn process_one(
167167
.map_err(sqlsonnet::Error::from)?;
168168

169169
let queries = Queries::from_json(&queries_json).map_err(|e| {
170-
eprintln!("{}", queries_json);
170+
// TODO: Print on stderr
171+
highlight(&queries_json, Language::Json, args).unwrap();
171172
e
172173
})?;
173174

sqlsonnet/src/error.rs

+36-25
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use itertools::Itertools;
2-
use miette::{Diagnostic, SourceCode};
2+
use miette::Diagnostic;
33

44
/// Errors
55
#[derive(thiserror::Error, Diagnostic, Debug)]
@@ -9,7 +9,7 @@ pub enum Error {
99
Jsonnet(#[from] JsonnetError),
1010
#[error(transparent)]
1111
#[diagnostic(transparent)]
12-
Json(#[from] JsonError),
12+
Json(#[from] Box<JsonError>),
1313
#[error(transparent)]
1414
#[diagnostic(transparent)]
1515
SqlParse(#[from] SQLParseError),
@@ -54,16 +54,43 @@ pub struct JsonError {
5454
pub reason: String,
5555
#[source_code]
5656
pub src: miette::NamedSource<String>,
57+
#[help]
58+
help: String,
5759
#[label]
58-
pub span: miette::SourceOffset,
60+
span: miette::SourceSpan,
5961
}
6062
impl JsonError {
61-
pub fn from(json: &str, e: serde_path_to_error::Error<serde_json::Error>) -> Self {
62-
let orig = e.inner();
63+
pub fn from(json: &str, e: serde_json::Error) -> Self {
6364
Self {
64-
reason: format!("{}; path `{}`", orig, e.path()),
65-
span: miette::SourceOffset::from_location(json, orig.line(), orig.column()),
65+
reason: e.to_string(),
66+
span: miette::SourceOffset::from_location(json, e.line(), e.column()).into(),
6667
src: miette::NamedSource::new("source.json", json.into()),
68+
help: "Jsonnet generated invalid JSON".into(),
69+
}
70+
}
71+
pub fn from_path(
72+
value: serde_json::Value,
73+
e: serde_path_to_error::Error<serde_json::Error>,
74+
) -> Self {
75+
let orig = e.inner();
76+
77+
let pointer = std::iter::once("".to_string())
78+
.chain(e.path().into_iter().map(|segment| match segment {
79+
serde_path_to_error::Segment::Seq { index } => index.to_string(),
80+
serde_path_to_error::Segment::Map { key } => key.into(),
81+
serde_path_to_error::Segment::Enum { variant } => variant.into(),
82+
serde_path_to_error::Segment::Unknown => String::default(),
83+
}))
84+
.join("/");
85+
let element = value
86+
.pointer(&pointer)
87+
.map(|v| serde_json::to_string_pretty(v).unwrap())
88+
.unwrap_or_default();
89+
Self {
90+
reason: orig.to_string(),
91+
span: miette::SourceSpan::new(0.into(), 0),
92+
src: miette::NamedSource::new("source.json", element),
93+
help: format!("at path {}", e.path()),
6794
}
6895
}
6996
}
@@ -121,24 +148,8 @@ impl From<Error> for FormattedError {
121148
}
122149
}
123150
Error::Json(json_source) => Self {
124-
message: source.to_string(),
125-
code: json_source
126-
.src
127-
.read_span(&miette::SourceSpan::new(json_source.span, 1), 2, 2)
128-
.ok()
129-
.and_then(|contents| String::from_utf8(contents.data().into()).ok())
130-
.map(|code| {
131-
let indent = code
132-
.lines()
133-
.filter(|l| !l.is_empty())
134-
.map(|l| l.chars().take_while(|c| c.is_whitespace()).count())
135-
.min()
136-
.unwrap_or_default();
137-
let indent: String = " ".repeat(indent);
138-
code.lines()
139-
.map(|l| l.strip_prefix(&indent).unwrap_or(l))
140-
.join("\n")
141-
}),
151+
message: format!("{} {}", source, json_source.help),
152+
code: Some(json_source.src.inner().clone()),
142153
location: None,
143154
},
144155

sqlsonnet/src/lib.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,10 @@ macro_rules! impl_conversions {
3636
}
3737
/// Convert from JSON.
3838
pub fn from_json(json: &str) -> Result<Self, Error> {
39-
let mut deserializer = serde_json::Deserializer::from_str(&json);
40-
Ok(serde_path_to_error::deserialize(&mut deserializer)
41-
.map_err(|e| crate::error::JsonError::from(&json, e))?)
39+
let deserializer: serde_json::Value = serde_json::from_str(json)
40+
.map_err(|e| Box::new(crate::error::JsonError::from(json, e)))?;
41+
Ok(serde_path_to_error::deserialize(&deserializer)
42+
.map_err(|e| Box::new(crate::error::JsonError::from_path(deserializer, e)))?)
4243
}
4344
/// Convert from Jsonnet.
4445
pub fn from_jsonnet<R: jsonnet::ImportResolver>(

sqlsonnet/src/queries.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ impl<'de> serde::de::Visitor<'de> for Visitor {
2424
A: serde::de::MapAccess<'de>,
2525
{
2626
loop {
27-
let Some(key) = map.next_key::<&'de str>()? else {
27+
let Some(key) = map.next_key::<String>()? else {
2828
break;
2929
};
3030
if key == "select" {

0 commit comments

Comments
 (0)