dry4rust/cli/
cli_error.rs1use std::error::Error;
7use std::fmt;
8use std::io;
9use std::path::PathBuf;
10
11use crate::error::Error as AnalysisError;
12
13#[derive(Debug)]
15pub enum CliError {
16 Io(io::Error),
18 NoSourceFiles(PathBuf),
20 NoRecognizedFiles,
22 AmbiguousLanguage(Vec<String>),
24 Analysis(AnalysisError),
26 InvalidFingerprint(String),
28 InvalidConfig(String),
30 CheckFailed,
32}
33
34impl CliError {
35 #[must_use]
37 pub const fn exit_code(&self) -> i32 {
38 match self {
39 Self::CheckFailed => 1,
40 Self::Io(_)
41 | Self::NoSourceFiles(_)
42 | Self::NoRecognizedFiles
43 | Self::AmbiguousLanguage(_)
44 | Self::Analysis(_)
45 | Self::InvalidFingerprint(_)
46 | Self::InvalidConfig(_) => 2,
47 }
48 }
49}
50
51impl fmt::Display for CliError {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 match self {
54 Self::Io(e) => write!(f, "{e}"),
55 Self::NoSourceFiles(path) => {
56 write!(f, "No source files found in {}", path.display())
57 }
58 Self::NoRecognizedFiles => {
59 write!(
60 f,
61 "No recognized source files found. Use --language to specify the language."
62 )
63 }
64 Self::AmbiguousLanguage(langs) => {
65 write!(
66 f,
67 "Multiple languages detected: {}. Use --language to specify which to analyze.",
68 langs.join(", ")
69 )
70 }
71 Self::Analysis(e) => write!(f, "{e}"),
72 Self::InvalidFingerprint(fp) => write!(f, "Invalid fingerprint: {fp}"),
73 Self::InvalidConfig(message) => write!(f, "{message}"),
74 Self::CheckFailed => write!(f, "Check failed"),
75 }
76 }
77}
78
79impl Error for CliError {
80 fn source(&self) -> Option<&(dyn Error + 'static)> {
81 match self {
82 Self::Io(e) => Some(e),
83 Self::Analysis(e) => Some(e),
84 _ => None,
85 }
86 }
87}
88
89impl From<io::Error> for CliError {
90 fn from(e: io::Error) -> Self {
91 Self::Io(e)
92 }
93}
94
95impl From<AnalysisError> for CliError {
96 fn from(e: AnalysisError) -> Self {
97 Self::Analysis(e)
98 }
99}
100
101pub type CliResult<T = ()> = Result<T, CliError>;