forked from mirrors/jj
revset: add origin field to RevsetParseError to chain alias errors
This could be embedded in a variant of RevsetParseErrorKind, but I want to keep the enum comparable.
This commit is contained in:
parent
7632466cc0
commit
5df25cd834
2 changed files with 33 additions and 1 deletions
|
@ -198,6 +198,7 @@ pub struct RevsetParser;
|
|||
pub struct RevsetParseError {
|
||||
kind: RevsetParseErrorKind,
|
||||
pest_error: Option<Box<pest::error::Error<Rule>>>,
|
||||
origin: Option<Box<RevsetParseError>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Error, PartialEq, Eq)]
|
||||
|
@ -219,6 +220,7 @@ impl RevsetParseError {
|
|||
RevsetParseError {
|
||||
kind,
|
||||
pest_error: None,
|
||||
origin: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,12 +234,36 @@ impl RevsetParseError {
|
|||
RevsetParseError {
|
||||
kind,
|
||||
pest_error: Some(Box::new(err)),
|
||||
origin: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn with_span_and_origin(
|
||||
kind: RevsetParseErrorKind,
|
||||
span: pest::Span<'_>,
|
||||
origin: Self,
|
||||
) -> Self {
|
||||
let err = pest::error::Error::new_from_span(
|
||||
pest::error::ErrorVariant::CustomError {
|
||||
message: kind.to_string(),
|
||||
},
|
||||
span,
|
||||
);
|
||||
RevsetParseError {
|
||||
kind,
|
||||
pest_error: Some(Box::new(err)),
|
||||
origin: Some(Box::new(origin)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> &RevsetParseErrorKind {
|
||||
&self.kind
|
||||
}
|
||||
|
||||
/// Original parsing error which typically occurred in an alias expression.
|
||||
pub fn origin(&self) -> Option<&Self> {
|
||||
self.origin.as_deref()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<pest::error::Error<Rule>> for RevsetParseError {
|
||||
|
@ -245,6 +271,7 @@ impl From<pest::error::Error<Rule>> for RevsetParseError {
|
|||
RevsetParseError {
|
||||
kind: RevsetParseErrorKind::SyntaxError,
|
||||
pest_error: Some(Box::new(err)),
|
||||
origin: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -261,6 +288,9 @@ impl fmt::Display for RevsetParseError {
|
|||
|
||||
impl error::Error for RevsetParseError {
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
if let Some(e) = self.origin() {
|
||||
return Some(e as &dyn error::Error);
|
||||
}
|
||||
match &self.kind {
|
||||
// SyntaxError is a wrapper for pest::error::Error.
|
||||
RevsetParseErrorKind::SyntaxError => {
|
||||
|
|
|
@ -16,6 +16,7 @@ use std::collections::{HashSet, VecDeque};
|
|||
use std::env::ArgsOs;
|
||||
use std::ffi::OsString;
|
||||
use std::fmt::Debug;
|
||||
use std::iter;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
@ -175,7 +176,8 @@ impl From<GitExportError> for CommandError {
|
|||
|
||||
impl From<RevsetParseError> for CommandError {
|
||||
fn from(err: RevsetParseError) -> Self {
|
||||
user_error(format!("Failed to parse revset: {err}"))
|
||||
let message = iter::successors(Some(&err), |e| e.origin()).join("\n");
|
||||
user_error(format!("Failed to parse revset: {message}"))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue