Skip to main content

rust_doctor/
error.rs

1use std::path::PathBuf;
2
3/// Top-level error for the rust-doctor scan pipeline.
4#[derive(thiserror::Error, Debug)]
5pub enum ScanError {
6    #[error(transparent)]
7    Discovery(#[from] DiscoveryError),
8
9    #[error("workspace resolution failed: {0}")]
10    Workspace(#[from] WorkspaceError),
11
12    #[error("diff resolution failed: {0}")]
13    Diff(#[from] DiffError),
14}
15
16/// Errors from workspace member resolution.
17#[derive(thiserror::Error, Debug)]
18pub enum WorkspaceError {
19    #[error("unknown workspace member '{name}'. Available members: {available}")]
20    UnknownMember { name: String, available: String },
21
22    #[error("workspace has no members")]
23    NoMembers,
24}
25
26/// Errors from diff mode resolution.
27#[derive(thiserror::Error, Debug)]
28pub enum DiffError {
29    #[error("invalid ref '{name}': {reason}")]
30    InvalidRef { name: String, reason: String },
31
32    #[error("git is not available or directory is not a git repository")]
33    GitNotFound,
34
35    #[error("failed to find merge base: {0}")]
36    MergeBaseFailed(String),
37
38    #[error("{0}")]
39    Other(String),
40}
41
42/// Errors from project discovery via `cargo metadata`.
43#[derive(thiserror::Error, Debug)]
44pub enum DiscoveryError {
45    #[error("cargo metadata failed: {source}")]
46    CargoMetadata {
47        #[source]
48        source: cargo_metadata::Error,
49    },
50
51    #[error("no packages found in workspace")]
52    NoPackages,
53}
54
55/// Errors from individual analysis passes.
56#[derive(thiserror::Error, Debug)]
57pub enum PassError {
58    #[error("{pass}: {message}")]
59    Failed { pass: String, message: String },
60
61    #[error("{pass}: analysis pass panicked")]
62    Panicked { pass: String },
63
64    #[error("{pass}: skipped ({reason})")]
65    Skipped { pass: String, reason: String },
66}
67
68/// Errors from project bootstrapping (shared between CLI and MCP).
69#[derive(thiserror::Error, Debug)]
70pub enum BootstrapError {
71    #[error("invalid directory '{path}': {source}")]
72    InvalidDirectory {
73        path: String,
74        #[source]
75        source: std::io::Error,
76    },
77
78    #[error("no Cargo.toml found in '{}'", path.display())]
79    NoCargo { path: PathBuf },
80
81    #[error(transparent)]
82    Discovery(#[from] DiscoveryError),
83}
84
85/// Errors from the interactive setup wizard.
86#[derive(thiserror::Error, Debug)]
87pub enum SetupError {
88    #[error(transparent)]
89    Prompt(#[from] dialoguer::Error),
90
91    #[error("{0}")]
92    NotInteractive(String),
93}
94
95/// Errors from loading the config file (`rust-doctor.toml`).
96#[derive(thiserror::Error, Debug)]
97pub enum ConfigError {
98    #[error("failed to read config file '{}': {source}", path.display())]
99    Io {
100        path: std::path::PathBuf,
101        #[source]
102        source: std::io::Error,
103    },
104
105    #[error("failed to parse config file '{}': {source}", path.display())]
106    Parse {
107        path: std::path::PathBuf,
108        #[source]
109        source: toml::de::Error,
110    },
111
112    #[error("failed to parse [package.metadata.rust-doctor] in Cargo.toml: {0}")]
113    MetadataParse(#[from] serde_json::Error),
114}