1use std::path::PathBuf;
4
5#[derive(Debug)]
7#[non_exhaustive]
8pub enum Error {
9 EntryNotFound(PathBuf, std::io::Error),
11 EntryIsDirectory(PathBuf),
13 UnsupportedFileType(String),
15 EntryNotInGraph(PathBuf),
17 SnapshotRead(PathBuf, std::io::Error),
19 SnapshotParse(PathBuf, serde_json::Error),
21 SnapshotWrite(PathBuf, std::io::Error),
23 MutuallyExclusiveFlags(String),
25 TargetIsEntryPoint(String),
27}
28
29impl Error {
30 pub fn hint(&self) -> Option<&str> {
32 match self {
33 Self::UnsupportedFileType(_) => {
34 Some("chainsaw supports TypeScript/JavaScript and Python files")
35 }
36 Self::EntryNotInGraph(_) => Some("is it reachable from the project root?"),
37 Self::TargetIsEntryPoint(flag) => Some(if flag == "--chain" {
38 "--chain finds import chains from the entry to a dependency"
39 } else {
40 "--cut finds where to sever import chains to a dependency"
41 }),
42 _ => None,
43 }
44 }
45}
46
47impl std::fmt::Display for Error {
50 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51 match self {
52 Self::EntryNotFound(path, source) => {
53 write!(f, "cannot find entry file '{}': {source}", path.display())
54 }
55 Self::EntryIsDirectory(path) => {
56 write!(f, "'{}' is a directory, not a source file", path.display())
57 }
58 Self::UnsupportedFileType(ext) => {
59 write!(f, "unsupported file type '.{ext}'")
60 }
61 Self::EntryNotInGraph(path) => {
62 write!(f, "entry file '{}' not found in graph", path.display())
63 }
64 Self::SnapshotRead(path, source) => {
65 write!(f, "cannot read snapshot '{}': {source}", path.display())
66 }
67 Self::SnapshotParse(path, source) => {
68 write!(f, "invalid snapshot '{}': {source}", path.display())
69 }
70 Self::SnapshotWrite(path, source) => {
71 write!(f, "cannot write snapshot '{}': {source}", path.display())
72 }
73 Self::MutuallyExclusiveFlags(flags) => {
74 write!(f, "{flags} cannot be used together")
75 }
76 Self::TargetIsEntryPoint(flag) => {
77 write!(f, "{flag} target is the entry point itself")
78 }
79 }
80 }
81}
82
83impl std::error::Error for Error {
85 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
86 match self {
87 Self::EntryNotFound(_, e)
88 | Self::SnapshotRead(_, e)
89 | Self::SnapshotWrite(_, e) => Some(e),
90 Self::SnapshotParse(_, e) => Some(e),
91 _ => None,
92 }
93 }
94}