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:
Yuya Nishihara 2022-11-25 18:46:30 +09:00
parent 7632466cc0
commit 5df25cd834
2 changed files with 33 additions and 1 deletions

View file

@ -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 => {

View file

@ -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}"))
}
}