Skip to main content

sage_loader/
error.rs

1//! Error types for the module loader.
2
3use miette::{Diagnostic, SourceSpan};
4use std::path::PathBuf;
5use thiserror::Error;
6
7/// Errors that can occur during module loading.
8#[derive(Debug, Error, Diagnostic)]
9pub enum LoadError {
10    /// File not found for a mod declaration.
11    #[error("module '{mod_name}' not found")]
12    #[diagnostic(
13        code(sage::loader::file_not_found),
14        help("Oswyn looked for: {}", searched.iter().map(|p| p.display().to_string()).collect::<Vec<_>>().join(", "))
15    )]
16    FileNotFound {
17        mod_name: String,
18        searched: Vec<PathBuf>,
19        #[label("declared here")]
20        span: SourceSpan,
21        #[source_code]
22        source_code: String,
23    },
24
25    /// IO error reading a file.
26    #[error("failed to read '{path}'")]
27    #[diagnostic(code(sage::loader::io_error))]
28    IoError {
29        path: PathBuf,
30        #[source]
31        source: std::io::Error,
32    },
33
34    /// Parse errors in a module.
35    #[error("parse error in '{file}': {}", errors.join("; "))]
36    #[diagnostic(code(sage::loader::parse_error))]
37    ParseError { file: PathBuf, errors: Vec<String> },
38
39    /// Circular dependency between modules.
40    #[error("circular dependency detected")]
41    #[diagnostic(
42        code(sage::loader::circular_dependency),
43        help("Oswyn traced the cycle: {}", cycle.join(" -> "))
44    )]
45    CircularDependency { cycle: Vec<String> },
46
47    /// Ambiguous module - both foo.sg and foo/mod.sg exist.
48    #[error("ambiguous module '{mod_name}'")]
49    #[diagnostic(
50        code(sage::loader::ambiguous_module),
51        help("Oswyn found both: {}", candidates.iter().map(|p| p.display().to_string()).collect::<Vec<_>>().join(" and "))
52    )]
53    AmbiguousModule {
54        mod_name: String,
55        candidates: Vec<PathBuf>,
56    },
57
58    /// Invalid manifest file.
59    #[error("invalid grove.toml")]
60    #[diagnostic(code(sage::loader::invalid_manifest))]
61    InvalidManifest {
62        path: PathBuf,
63        #[source]
64        source: toml::de::Error,
65    },
66
67    /// Missing entry point in manifest.
68    #[error("entry point not found: '{path}'")]
69    #[diagnostic(code(sage::loader::missing_entry))]
70    MissingEntry { path: PathBuf },
71
72    /// No grove.toml found when expected.
73    #[error("no grove.toml found in '{dir}' or parent directories")]
74    #[diagnostic(code(sage::loader::no_manifest))]
75    NoManifest { dir: PathBuf },
76
77    /// Package manager error.
78    #[error("{source}")]
79    #[diagnostic(transparent)]
80    PackageError {
81        #[from]
82        source: sage_package::PackageError,
83    },
84}