1use std::fmt;
2
3#[derive(Debug)]
8pub enum AftError {
9 SymbolNotFound {
10 name: String,
11 file: String,
12 },
13 AmbiguousSymbol {
14 name: String,
15 candidates: Vec<String>,
16 },
17 ParseError {
18 message: String,
19 },
20 FileNotFound {
21 path: String,
22 },
23 InvalidRequest {
24 message: String,
25 },
26 CheckpointNotFound {
27 name: String,
28 },
29 NoUndoHistory {
30 path: String,
31 },
32 AmbiguousMatch {
33 pattern: String,
34 count: usize,
35 },
36 ScopeNotFound {
37 scope: String,
38 available: Vec<String>,
39 file: String,
40 },
41 MemberNotFound {
42 member: String,
43 scope: String,
44 file: String,
45 },
46}
47
48impl AftError {
49 pub fn code(&self) -> &'static str {
51 match self {
52 AftError::SymbolNotFound { .. } => "symbol_not_found",
53 AftError::AmbiguousSymbol { .. } => "ambiguous_symbol",
54 AftError::ParseError { .. } => "parse_error",
55 AftError::FileNotFound { .. } => "file_not_found",
56 AftError::InvalidRequest { .. } => "invalid_request",
57 AftError::CheckpointNotFound { .. } => "checkpoint_not_found",
58 AftError::NoUndoHistory { .. } => "no_undo_history",
59 AftError::AmbiguousMatch { .. } => "ambiguous_match",
60 AftError::ScopeNotFound { .. } => "scope_not_found",
61 AftError::MemberNotFound { .. } => "member_not_found",
62 }
63 }
64
65 pub fn to_error_json(&self) -> serde_json::Value {
69 serde_json::json!({
70 "code": self.code(),
71 "message": self.to_string(),
72 })
73 }
74}
75
76impl fmt::Display for AftError {
77 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 match self {
79 AftError::SymbolNotFound { name, file } => {
80 write!(f, "symbol '{}' not found in {}", name, file)
81 }
82 AftError::AmbiguousSymbol { name, candidates } => {
83 write!(
84 f,
85 "symbol '{}' is ambiguous, candidates: [{}]",
86 name,
87 candidates.join(", ")
88 )
89 }
90 AftError::ParseError { message } => {
91 write!(f, "parse error: {}", message)
92 }
93 AftError::FileNotFound { path } => {
94 write!(f, "file not found: {}", path)
95 }
96 AftError::InvalidRequest { message } => {
97 write!(f, "invalid request: {}", message)
98 }
99 AftError::CheckpointNotFound { name } => {
100 write!(f, "checkpoint not found: {}", name)
101 }
102 AftError::NoUndoHistory { path } => {
103 write!(f, "no undo history for: {}", path)
104 }
105 AftError::AmbiguousMatch { pattern, count } => {
106 write!(
107 f,
108 "pattern '{}' matches {} occurrences, expected exactly 1",
109 pattern, count
110 )
111 }
112 AftError::ScopeNotFound {
113 scope,
114 available,
115 file,
116 } => {
117 if available.is_empty() {
118 write!(
119 f,
120 "scope '{}' not found in {} (no scopes available)",
121 scope, file
122 )
123 } else {
124 write!(
125 f,
126 "scope '{}' not found in {}, available: [{}]",
127 scope,
128 file,
129 available.join(", ")
130 )
131 }
132 }
133 AftError::MemberNotFound {
134 member,
135 scope,
136 file,
137 } => {
138 write!(
139 f,
140 "member '{}' not found in scope '{}' in {}",
141 member, scope, file
142 )
143 }
144 }
145 }
146}
147
148impl std::error::Error for AftError {}