#[allow(unused)] use crate::prelude::*; use crate::parser::Span; use derive_new::new; use language_reporting::{Diagnostic, Label, Severity}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Serialize, Deserialize)] pub enum ShellError { String(StringError), TypeError(String), MissingProperty { subpath: String, expr: String }, Diagnostic(ShellDiagnostic), } impl ShellError { crate fn parse_error( error: nom::Err<(nom_locate::LocatedSpan<&str>, nom::error::ErrorKind)>, ) -> ShellError { use language_reporting::*; match error { nom::Err::Incomplete(_) => unreachable!(), nom::Err::Failure(span) | nom::Err::Error(span) => { let diagnostic = Diagnostic::new(Severity::Error, format!("{:?}", span)) .with_label(Label::new_primary(Span::from(span.0))); ShellError::diagnostic(diagnostic) // nom::Context::Code(span, kind) => { // let diagnostic = // Diagnostic::new(Severity::Error, format!("{}", kind.description())) // .with_label(Label::new_primary(Span::from(span))); // ShellError::diagnostic(diagnostic) // } } // ParseError::UnrecognizedToken { // token: (start, SpannedToken { token, .. }, end), // expected, // } => { // let diagnostic = Diagnostic::new( // Severity::Error, // format!("Unexpected {:?}, expected {:?}", token, expected), // ) // .with_label(Label::new_primary(Span::from((start, end)))); // ShellError::diagnostic(diagnostic) // } // ParseError::User { error } => error, // other => ShellError::string(format!("{:?}", other)), } } crate fn diagnostic(diagnostic: Diagnostic) -> ShellError { ShellError::Diagnostic(ShellDiagnostic { diagnostic }) } crate fn labeled_error( msg: impl Into, label: impl Into, span: Span, ) -> ShellError { ShellError::diagnostic( Diagnostic::new(Severity::Error, msg.into()) .with_label(Label::new_primary(span).with_message(label.into())), ) } crate fn maybe_labeled_error( msg: impl Into, label: impl Into, span: Option, ) -> ShellError { match span { Some(span) => ShellError::diagnostic( Diagnostic::new(Severity::Error, msg.into()) .with_label(Label::new_primary(span).with_message(label.into())), ), None => ShellError::string(msg), } } crate fn string(title: impl Into) -> ShellError { ShellError::String(StringError::new(title.into(), Value::nothing())) } crate fn unimplemented(title: impl Into) -> ShellError { ShellError::string(&format!("Unimplemented: {}", title.into())) } crate fn unexpected(title: impl Into) -> ShellError { ShellError::string(&format!("Unexpected: {}", title.into())) } crate fn copy_error(&self) -> ShellError { self.clone() } } #[derive(Debug, Clone)] pub struct ShellDiagnostic { crate diagnostic: Diagnostic, } impl ShellDiagnostic { #[allow(unused)] crate fn simple_diagnostic( span: impl Into, source: impl Into, ) -> ShellDiagnostic { use language_reporting::*; let span = span.into(); let source = source.into(); let diagnostic = Diagnostic::new(Severity::Error, "Parse error").with_label(Label::new_primary(span)); ShellDiagnostic { diagnostic } } } impl PartialEq for ShellDiagnostic { fn eq(&self, _other: &ShellDiagnostic) -> bool { false } } impl Eq for ShellDiagnostic {} impl std::cmp::PartialOrd for ShellDiagnostic { fn partial_cmp(&self, _other: &Self) -> Option { Some(std::cmp::Ordering::Less) } } impl std::cmp::Ord for ShellDiagnostic { fn cmp(&self, _other: &Self) -> std::cmp::Ordering { std::cmp::Ordering::Less } } impl Serialize for ShellDiagnostic { fn serialize(&self, serializer: S) -> Result where S: Serializer, { "".serialize(serializer) } } impl Deserialize<'de> for ShellDiagnostic { fn deserialize(_deserializer: D) -> Result where D: Deserializer<'de>, { Ok(ShellDiagnostic { diagnostic: Diagnostic::new( language_reporting::Severity::Error, "deserialize not implemented for ShellDiagnostic", ), }) } } #[derive(Debug, Ord, PartialOrd, Eq, PartialEq, new, Clone, Serialize, Deserialize)] pub struct StringError { title: String, error: Value, } impl std::fmt::Display for ShellError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { ShellError::String(s) => write!(f, "{}", &s.title), ShellError::TypeError { .. } => write!(f, "TypeError"), ShellError::MissingProperty { .. } => write!(f, "MissingProperty"), ShellError::Diagnostic(_) => write!(f, ""), } } } impl std::error::Error for ShellError {} impl std::convert::From for ShellError { fn from(input: std::io::Error) -> ShellError { ShellError::String(StringError { title: format!("{}", input), error: Value::nothing(), }) } } impl std::convert::From for ShellError { fn from(_input: futures_sink::VecSinkError) -> ShellError { ShellError::String(StringError { title: format!("Unexpected Vec Sink Error"), error: Value::nothing(), }) } } impl std::convert::From for ShellError { fn from(input: subprocess::PopenError) -> ShellError { ShellError::String(StringError { title: format!("{}", input), error: Value::nothing(), }) } } // impl std::convert::From> for ShellError { // fn from(input: nom::Err<(&str, nom::ErrorKind)>) -> ShellError { // ShellError::String(StringError { // title: format!("{:?}", input), // error: Value::nothing(), // }) // } // } impl std::convert::From for ShellError { fn from(input: toml::ser::Error) -> ShellError { ShellError::String(StringError { title: format!("{:?}", input), error: Value::nothing(), }) } }