1use std::error::Error;
4use std::fmt::Display;
5use std::io::Error as IoError;
6use std::path::PathBuf;
7
8use wdl_analysis::AnalysisResult;
9
10pub type DocResult<T> = Result<T, DocError>;
12
13pub(crate) trait ResultContextExt {
15 fn with_context<F, C>(self, context: F) -> Self
17 where
18 F: FnOnce() -> C,
19 C: Display;
20}
21
22impl<T> ResultContextExt for DocResult<T> {
23 fn with_context<F, C>(self, context: F) -> Self
24 where
25 F: FnOnce() -> C,
26 C: Display,
27 {
28 self.map_err(|e| e.with_context(context()))
29 }
30}
31
32#[derive(Debug)]
34pub enum NpmError {
35 Build(IoError),
37 Install(IoError),
39 SearchIndex(IoError),
41 Tailwind(IoError),
43}
44
45impl Display for NpmError {
46 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 match self {
48 NpmError::Build(e) => write!(f, "failed to run `npm run build`: {e}"),
49 NpmError::Install(e) => write!(f, "failed to run `npm install`: {e}"),
50 NpmError::SearchIndex(e) => write!(f, "failed to run `npx pagefind`: {e}"),
51 NpmError::Tailwind(e) => write!(f, "failed to run `npx @tailwindcss/cli`: {e}"),
52 }
53 }
54}
55
56#[derive(Debug)]
58pub enum DocErrorKind {
59 WorkspaceNotFound(PathBuf),
61 NoDocuments,
63 Analyzer(anyhow::Error),
65 AnalysisFailed(Vec<AnalysisResult>),
69 Npm(NpmError),
71 Io(IoError),
73}
74
75#[derive(Debug)]
77pub struct DocError {
78 context: Option<String>,
80 kind: DocErrorKind,
82}
83
84impl DocError {
85 pub fn new(kind: DocErrorKind) -> Self {
87 Self {
88 kind,
89 context: None,
90 }
91 }
92
93 pub fn kind(&self) -> &DocErrorKind {
95 &self.kind
96 }
97
98 pub fn with_context(self, context: impl Display) -> Self {
100 Self {
101 context: Some(context.to_string()),
102 kind: self.kind,
103 }
104 }
105}
106
107impl Display for DocError {
108 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109 if let Some(ref ctx) = self.context {
110 write!(f, "{ctx}: ")?;
111 }
112
113 match &self.kind {
114 DocErrorKind::WorkspaceNotFound(root) => {
115 write!(
116 f,
117 "workspace root `{}` not found in analysis results",
118 root.display()
119 )
120 }
121 DocErrorKind::NoDocuments => write!(f, "no WDL documents found in analysis"),
122 DocErrorKind::Analyzer(e) => write!(f, "{e}"),
123 DocErrorKind::AnalysisFailed(_) => {
124 write!(f, "a WDL document in the workspace has analysis errors")
125 }
126 DocErrorKind::Npm(e) => write!(f, "{e}"),
127 DocErrorKind::Io(e) => write!(f, "{e}"),
128 }
129 }
130}
131
132impl Error for DocError {}
133
134impl From<NpmError> for DocError {
135 fn from(e: NpmError) -> Self {
136 DocError::new(DocErrorKind::Npm(e))
137 }
138}
139
140impl From<IoError> for DocError {
141 fn from(e: IoError) -> Self {
142 DocError::new(DocErrorKind::Io(e))
143 }
144}
145
146impl From<DocErrorKind> for DocError {
147 fn from(e: DocErrorKind) -> Self {
148 DocError::new(e)
149 }
150}