1use crate::conversions::Error::FormatFailed;
2use crate::{conversions, io};
3use console::{Style, StyledObject};
4use gesha_collections::partial_result::PartialResult;
5use std::path::PathBuf;
6
7pub type Result<A> = std::result::Result<A, Error>;
8
9pub type Output<A> = PartialResult<A, Error>;
10
11#[derive(Debug)]
12pub enum Error {
13 OpenApiTypes {
14 path: PathBuf,
15 cause: openapi_types::Error,
16 },
17
18 Conversion {
19 path: PathBuf,
20 cause: conversions::Error,
21 },
22
23 Io(io::Error),
24
25 Multiple(Vec<Self>),
26
27 #[cfg(feature = "testing")]
28 Testing(crate::testing::Error),
29}
30
31impl Error {
32 pub fn detail(&self, theme: ErrorTheme) -> String {
33 match self {
34 Error::Conversion {
35 cause: FormatFailed { detail },
36 ..
37 } => {
38 format!("rustfmt>\n{}", detail)
39 }
40 Error::Conversion {
41 path,
42 cause: conversions::Error::TransformBroken { detail },
43 } => {
44 format!(
45 "internal error: transform broken.\n{}\n{}",
46 path.display(),
47 detail,
48 )
49 }
50 Error::Multiple(errors) => errors
51 .iter()
52 .map(|e| e.detail(theme))
53 .collect::<Vec<_>>()
54 .join("\n"),
55
56 #[cfg(feature = "testing")]
57 Error::Testing(crate::testing::Error::DiffDetected {
58 output,
59 actual,
60 expected,
61 }) => {
62 let style = theme.diff_style();
63 format!(
64 "\n {: <10} : {}\n {} : {}\n\n{}",
65 style.src_lines,
66 actual.to_string_lossy(),
67 style.dst_lines,
68 expected.to_string_lossy(),
69 output
70 )
71 }
72 _ => {
73 format!("{:#?}", self)
74 }
75 }
76 }
77 pub fn conversion<A: Into<PathBuf>>(path: A) -> impl Fn(conversions::Error) -> Self {
78 let path = path.into();
79 move |cause| Self::Conversion {
80 path: path.clone(),
81 cause,
82 }
83 }
84 pub fn openapi<A: Into<PathBuf>>(path: A) -> impl Fn(openapi_types::Error) -> Self {
85 let path = path.into();
86 move |cause| Self::OpenApiTypes {
87 path: path.clone(),
88 cause,
89 }
90 }
91 pub fn dump(&self) -> String {
92 self.detail(ErrorTheme::Test)
93 }
94}
95
96#[derive(Copy, Clone)]
97pub enum ErrorTheme {
98 Test,
99 Overwrite,
100}
101
102pub struct DiffStyle {
103 src_lines: StyledObject<&'static str>,
104 dst_lines: StyledObject<&'static str>,
105}
106
107impl ErrorTheme {
108 pub fn diff_style(&self) -> DiffStyle {
109 match self {
110 ErrorTheme::Test => DiffStyle {
111 src_lines: Style::new().red().apply_to("- actual"),
112 dst_lines: Style::new().green().apply_to("+ expected"),
113 },
114 ErrorTheme::Overwrite => DiffStyle {
115 src_lines: Style::new().red().apply_to("- current"),
116 dst_lines: Style::new().green().apply_to("+ modified"),
117 },
118 }
119 }
120}