mon_core/
error.rs

1use miette::{Diagnostic, NamedSource, SourceSpan};
2use std::sync::Arc;
3use thiserror::Error;
4
5#[derive(Error, Debug, Diagnostic, Clone)]
6pub enum MonError {
7    #[error(transparent)]
8    #[diagnostic(transparent)]
9    #[source_code]
10    Parser(Box<ParserError>),
11
12    #[error(transparent)]
13    #[diagnostic(transparent)]
14    #[source_code]
15    Resolver(Box<ResolverError>),
16}
17
18impl From<ParserError> for MonError {
19    fn from(err: ParserError) -> Self {
20        MonError::Parser(Box::new(err))
21    }
22}
23
24impl From<ResolverError> for MonError {
25    fn from(err: ResolverError) -> Self {
26        MonError::Resolver(Box::new(err))
27    }
28}
29
30#[derive(Error, Debug, Diagnostic, Clone)]
31#[error("Parser Error")]
32pub enum ParserError {
33    #[error("Unexpected token")]
34    #[diagnostic(
35        code(parser::unexpected_token),
36        help("The parser found a token it did not expect in this position.")
37    )]
38    UnexpectedToken {
39        #[source_code]
40        src: Arc<NamedSource<String>>,
41        #[label("Expected {expected}, but found this")]
42        span: SourceSpan,
43        expected: String,
44    },
45
46    #[error("Unexpected end of file")]
47    #[diagnostic(
48        code(parser::unexpected_eof),
49        help("The file ended unexpectedly. The parser expected more tokens.")
50    )]
51    UnexpectedEof {
52        #[source_code]
53        src: Arc<NamedSource<String>>,
54        #[label("File ended unexpectedly here")]
55        span: SourceSpan,
56    },
57
58    #[error("Missing expected token")]
59    #[diagnostic(
60        code(parser::missing_expected_token),
61        help("The parser expected a specific token that was not found.")
62    )]
63    MissingExpectedToken {
64        #[source_code]
65        src: Arc<NamedSource<String>>,
66        #[label("Expected {expected} here")]
67        span: SourceSpan,
68        expected: String,
69    },
70}
71#[derive(Error, Debug, Diagnostic, Clone)]
72#[error("Resolver Error")]
73pub enum ResolverError {
74    #[error("Module not found at path: {path}")]
75    #[diagnostic(
76        code(resolver::module_not_found),
77        help("Check that the path is correct and the file exists.")
78    )]
79    ModuleNotFound {
80        path: String,
81        #[source_code]
82        src: Arc<NamedSource<String>>,
83        #[label("...referenced here")]
84        span: SourceSpan,
85    },
86
87    #[error("Anchor '&{name}' not found")]
88    #[diagnostic(
89        code(resolver::anchor_not_found),
90        help("Ensure the anchor is defined with '&{name}: ...' in the correct scope.")
91    )]
92    AnchorNotFound {
93        name: String,
94        #[source_code]
95        src: Arc<NamedSource<String>>,
96        #[label("This anchor was not found")]
97        span: SourceSpan,
98    },
99
100    #[error("Cannot spread a non-object value")]
101    #[diagnostic(
102        code(resolver::spread_on_non_object),
103        help("The '...*' operator can only be used on an object anchor inside another object.")
104    )]
105    SpreadOnNonObject {
106        name: String,
107        #[source_code]
108        src: Arc<NamedSource<String>>,
109        #[label("'{name}' does not point to an object")]
110        span: SourceSpan,
111    },
112
113    #[error("Cannot spread a non-array value")]
114    #[diagnostic(
115        code(resolver::spread_on_non_array),
116        help("The '...*' operator can only be used on an array anchor inside another array.")
117    )]
118    SpreadOnNonArray {
119        name: String,
120        #[source_code]
121        src: Arc<NamedSource<String>>,
122        #[label("'{name}' does not point to an array")]
123        span: SourceSpan,
124    },
125
126    #[error("Circular dependency detected")]
127    #[diagnostic(
128        code(resolver::circular_dependency),
129        help("The following import chain forms a loop: {cycle}")
130    )]
131    CircularDependency {
132        cycle: String,
133        #[source_code]
134        src: Arc<NamedSource<String>>,
135        #[label("Importing this module creates a cycle")]
136        span: SourceSpan,
137    },
138
139    #[error(transparent)]
140    #[diagnostic(transparent)]
141    Validation(#[from] ValidationError),
142
143    #[error(transparent)]
144    #[diagnostic(transparent)]
145    WrappedParserError(Box<ParserError>),
146}
147
148impl From<ParserError> for ResolverError {
149    fn from(err: ParserError) -> Self {
150        ResolverError::WrappedParserError(Box::new(err))
151    }
152}
153
154#[derive(Error, Debug, Diagnostic, Clone)]
155#[error("Validation Error")]
156pub enum ValidationError {
157    #[error("Type mismatch for field '{field_name}'. Expected type {expected_type} but got {found_type}.")]
158    #[diagnostic(
159        code(validation::type_mismatch),
160        help(
161            "Ensure the value's type matches the expected type in the struct or enum definition."
162        )
163    )]
164    TypeMismatch {
165        field_name: String,
166        expected_type: String,
167        found_type: String,
168        #[source_code]
169        src: Arc<NamedSource<String>>,
170        #[label("Type mismatch here")]
171        span: SourceSpan,
172    },
173
174    #[error("Missing required field '{field_name}' for struct '{struct_name}'.")]
175    #[diagnostic(
176        code(validation::missing_field),
177        help("Add the missing field or make it optional in the struct definition.")
178    )]
179    MissingField {
180        field_name: String,
181        struct_name: String,
182        #[source_code]
183        src: Arc<NamedSource<String>>,
184        #[label("Field '{field_name}' is missing here")]
185        span: SourceSpan,
186    },
187
188    #[error("Found unexpected field '{field_name}' not defined in struct '{struct_name}'.")]
189    #[diagnostic(
190        code(validation::unexpected_field),
191        help("Remove the unexpected field or add it to the struct definition.")
192    )]
193    UnexpectedField {
194        field_name: String,
195        struct_name: String,
196        #[source_code]
197        src: Arc<NamedSource<String>>,
198        #[label("Unexpected field here")]
199        span: SourceSpan,
200    },
201
202    #[error("Undefined type '{type_name}'.")]
203    #[diagnostic(
204        code(validation::undefined_type),
205        help("Ensure the type is defined or imported correctly.")
206    )]
207    UndefinedType {
208        type_name: String,
209        #[source_code]
210        src: Arc<NamedSource<String>>,
211        #[label("Undefined type used here")]
212        span: SourceSpan,
213    },
214
215    #[error("Variant '{variant_name}' is not defined in enum '{enum_name}'.")]
216    #[diagnostic(
217        code(validation::undefined_enum_variant),
218        help("Ensure the enum variant exists in the enum definition.")
219    )]
220    UndefinedEnumVariant {
221        variant_name: String,
222        enum_name: String,
223        #[source_code]
224        src: Arc<NamedSource<String>>,
225        #[label("Undefined enum variant used here")]
226        span: SourceSpan,
227    },
228
229    #[error("Complex collection type validation not yet implemented for field '{field_name}'.")]
230    #[diagnostic(
231        code(validation::unimplemented_collection_validation),
232        help("This type of collection validation is not yet supported.")
233    )]
234    UnimplementedCollectionValidation {
235        field_name: String,
236        #[source_code]
237        src: Arc<NamedSource<String>>,
238        #[label("Complex collection type here")]
239        span: SourceSpan,
240    },
241}
242
243impl From<MonError> for ResolverError {
244    fn from(err: MonError) -> Self {
245        match err {
246            MonError::Parser(p_err) => ResolverError::WrappedParserError(p_err),
247            MonError::Resolver(r_err) => *r_err,
248        }
249    }
250}