nu_protocol/errors/
chained_error.rs1use super::shell_error::ShellError;
2use crate::Span;
3use miette::{LabeledSpan, Severity, SourceCode};
4use thiserror::Error;
5
6#[derive(Debug, Clone, PartialEq, Error)]
15pub struct ChainedError {
16 first: bool,
17 pub(crate) sources: Vec<ShellError>,
18 span: Span,
19}
20
21impl std::fmt::Display for ChainedError {
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 if self.first {
24 write!(f, "{}", self.sources[0])
25 } else {
26 write!(f, "oops")
27 }
28 }
29}
30
31impl ChainedError {
32 pub fn new(source: ShellError, span: Span) -> Self {
33 Self {
34 first: true,
35 sources: vec![source],
36 span,
37 }
38 }
39
40 pub fn new_chained(sources: Self, span: Span) -> Self {
41 Self {
42 first: false,
43 sources: vec![ShellError::ChainedError(sources)],
44 span,
45 }
46 }
47}
48
49impl miette::Diagnostic for ChainedError {
50 fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn miette::Diagnostic> + 'a>> {
51 if self.first {
52 self.sources[0].related()
53 } else {
54 Some(Box::new(self.sources.iter().map(|s| s as _)))
55 }
56 }
57
58 fn code<'a>(&'a self) -> Option<Box<dyn std::fmt::Display + 'a>> {
59 if self.first {
60 self.sources[0].code()
61 } else {
62 Some(Box::new("chained_error"))
63 }
64 }
65
66 fn severity(&self) -> Option<Severity> {
67 if self.first {
68 self.sources[0].severity()
69 } else {
70 None
71 }
72 }
73
74 fn help<'a>(&'a self) -> Option<Box<dyn std::fmt::Display + 'a>> {
75 if self.first {
76 self.sources[0].help()
77 } else {
78 None
79 }
80 }
81
82 fn url<'a>(&'a self) -> Option<Box<dyn std::fmt::Display + 'a>> {
83 if self.first {
84 self.sources[0].url()
85 } else {
86 None
87 }
88 }
89
90 fn labels<'a>(&'a self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + 'a>> {
91 if self.first {
92 self.sources[0].labels()
93 } else {
94 Some(Box::new(
95 vec![LabeledSpan::new_with_span(
96 Some("error happened when running this".to_string()),
97 self.span,
98 )]
99 .into_iter(),
100 ))
101 }
102 }
103
104 fn source_code(&self) -> Option<&dyn SourceCode> {
106 if self.first {
107 self.sources[0].source_code()
108 } else {
109 None
110 }
111 }
112
113 fn diagnostic_source(&self) -> Option<&dyn miette::Diagnostic> {
114 if self.first {
115 self.sources[0].diagnostic_source()
116 } else {
117 None
118 }
119 }
120}