1use std::path::PathBuf;
2
3use rustyfi_syntax::{ParseFileError, RustyfiVersion};
4
5#[derive(Debug, thiserror::Error)]
7pub enum LoadError {
8 #[error("{path}: {source}")]
10 Io {
11 path: PathBuf,
12 #[source]
13 source: std::io::Error,
14 },
15
16 #[error("{path}: {source}")]
19 Parse {
20 path: PathBuf,
21 #[source]
22 source: ParseFileError,
23 },
24
25 #[error(
27 "cannot resolve `@require: {name}`; searched: {}",
28 format_searched(.searched)
29 )]
30 UnresolvedRequire {
31 name: String,
32 searched: Vec<PathBuf>,
33 },
34
35 #[error(
37 "cannot resolve `@import: {name}` from {}; searched: {}",
38 .from.display(),
39 format_searched(.searched)
40 )]
41 UnresolvedImport {
42 name: String,
43 from: PathBuf,
44 searched: Vec<PathBuf>,
45 },
46
47 #[error("dependency cycle detected: {}", format_chain(.chain))]
51 Cycle { chain: Vec<PathBuf> },
52
53 #[error(
56 "{path}: required/imported file must be a library (no `in ...` body), found a document"
57 )]
58 DocumentAsDependency { path: PathBuf },
59
60 #[error("{path}: entry file must be a document (with an `in ...` body), found a library")]
62 LibraryAsEntry { path: PathBuf },
63
64 #[error(
67 "SATySFi {requested} documents are not supported yet; supported: {}",
68 format_versions(.supported)
69 )]
70 UnsupportedVersion {
71 requested: RustyfiVersion,
72 supported: Vec<RustyfiVersion>,
73 },
74
75 #[error(
78 "SATySFi {version} has no `use` headers; `Envelopes` mode requires 0.1 \
79 (drop --deps, or pass --lang 0.1)"
80 )]
81 InvalidModeVersion { version: RustyfiVersion },
82
83 #[error(
86 "{from}: cannot resolve `use package {module}` — no pre-resolved \
87 dependency graph; pass --deps <rustyfi-deps.yaml>"
88 )]
89 PackageDependencyUnresolved { module: String, from: PathBuf },
90
91 #[error(
96 "{from}: bare `use {module}` is only allowed between files inside one \
97 package; a document must say `use package {module}` or `use {module} \
98 of \"<path>\"`"
99 )]
100 BareUseOutsidePackage { module: String, from: PathBuf },
101
102 #[error(
104 "cannot resolve `use … of `{relpath}`` from {}; searched: {}",
105 .from.display(),
106 format_searched(.searched)
107 )]
108 UnresolvedUseOf {
109 relpath: String,
110 from: PathBuf,
111 searched: Vec<PathBuf>,
112 },
113
114 #[error(
117 "{from}: `{header}` requires Envelopes mode (pass --deps, or let a \
118 `use` header pin it); this load ran in Legacy (@require/@import) mode"
119 )]
120 EnvelopeHeaderUnderLegacy { header: String, from: PathBuf },
121
122 #[error(
125 "{from}: `{header}` is a Legacy (@require/@import) header; Envelopes \
126 mode resolves `use package` / `use … of` headers only"
127 )]
128 LegacyHeaderUnderEnvelopes { header: String, from: PathBuf },
129
130 #[error("{path}: cannot read rustyfi-deps.yaml: {source}")]
133 DepsConfigNotFound {
134 path: PathBuf,
135 #[source]
136 source: std::io::Error,
137 },
138
139 #[error("{path}: invalid rustyfi-deps.yaml: {message}")]
147 DepsConfigDecode { path: PathBuf, message: String },
148
149 #[error("{path}: cannot read rustyfi-envelope.yaml: {source}")]
152 EnvelopeConfigNotFound {
153 path: PathBuf,
154 #[source]
155 source: std::io::Error,
156 },
157
158 #[error("{path}: invalid rustyfi-envelope.yaml: {message}")]
164 EnvelopeConfigDecode { path: PathBuf, message: String },
165
166 #[error("{path}: cannot list envelope source directory: {source}")]
169 CannotReadDirectory {
170 path: PathBuf,
171 #[source]
172 source: std::io::Error,
173 },
174
175 #[error("rustyfi-deps.yaml: two envelopes are named `{name}`")]
178 EnvelopeNameConflict { name: String },
179
180 #[error("envelope `{depending}` depends on unknown envelope `{depended}`")]
184 DependencyOnUnknownEnvelope { depending: String, depended: String },
185
186 #[error("envelope dependency cycle: {}", .chain.join(" -> "))]
190 CyclicEnvelopeDependency { chain: Vec<String> },
191
192 #[error(
196 "envelope module `{module}` is declared by both {} and {}",
197 .prev.display(),
198 .path.display()
199 )]
200 FileModuleNameConflict {
201 module: String,
202 prev: PathBuf,
203 path: PathBuf,
204 },
205
206 #[error("{from}: `use {module}` names no module in this envelope")]
209 FileModuleNotFound { module: String, from: PathBuf },
210
211 #[error(
214 "{from}: `use {module} of …` is not allowed inside a package; package \
215 files address siblings by bare `use <Module>`"
216 )]
217 UseOfInsidePackage { module: String, from: PathBuf },
218
219 #[error(
224 "{from}: `use package {module}` does not match any dependency alias \
225 (`used_as`) in the supplied rustyfi-deps.yaml"
226 )]
227 UnknownPackageDependency { module: String, from: PathBuf },
228}
229
230fn format_versions(versions: &[RustyfiVersion]) -> String {
231 versions
232 .iter()
233 .map(|v| v.to_string())
234 .collect::<Vec<_>>()
235 .join(", ")
236}
237
238fn format_searched(searched: &[PathBuf]) -> String {
239 if searched.is_empty() {
240 "(no candidates; is `lib_root` configured?)".to_string()
241 } else {
242 searched
243 .iter()
244 .map(|p| p.display().to_string())
245 .collect::<Vec<_>>()
246 .join(", ")
247 }
248}
249
250fn format_chain(chain: &[PathBuf]) -> String {
251 chain
252 .iter()
253 .map(|p| p.display().to_string())
254 .collect::<Vec<_>>()
255 .join(" -> ")
256}