alef_core/config/resolved/
imports.rs1use super::ResolvedCrateConfig;
4use crate::config::extras::Language;
5use crate::config::resolve_helpers::find_after_crates_prefix;
6
7impl ResolvedCrateConfig {
8 pub fn core_import_name(&self) -> String {
13 self.core_import.clone().unwrap_or_else(|| self.name.replace('-', "_"))
14 }
15
16 pub fn error_type_name(&self) -> String {
20 self.error_type.clone().unwrap_or_else(|| "Error".to_string())
21 }
22
23 pub fn error_constructor_expr(&self) -> String {
28 self.error_constructor
29 .clone()
30 .unwrap_or_else(|| format!("{}::{}::from({{msg}})", self.core_import_name(), self.error_type_name()))
31 }
32
33 pub fn core_crate_dir(&self) -> String {
39 if let Some(first_source) = self.sources.first() {
42 let path = std::path::Path::new(first_source);
43 let mut current = path.parent();
44 while let Some(dir) = current {
45 if dir.file_name().is_some_and(|n| n == "src") {
46 if let Some(crate_dir) = dir.parent() {
47 if let Some(dir_name) = crate_dir.file_name() {
48 return dir_name.to_string_lossy().into_owned();
49 }
50 }
51 break;
52 }
53 current = dir.parent();
54 }
55 }
56 self.name.clone()
57 }
58
59 pub fn core_crate_for_language(&self, lang: Language) -> String {
65 let override_name = match lang {
66 Language::Wasm => self.wasm.as_ref().and_then(|c| c.core_crate_override.as_deref()),
67 Language::Dart => self.dart.as_ref().and_then(|c| c.core_crate_override.as_deref()),
68 Language::Swift => self.swift.as_ref().and_then(|c| c.core_crate_override.as_deref()),
69 _ => None,
70 };
71 match override_name {
72 Some(name) => name.to_string(),
73 None => self.core_crate_dir(),
74 }
75 }
76
77 pub fn core_import_for_language(&self, lang: Language) -> String {
84 let override_name = match lang {
85 Language::Wasm => self.wasm.as_ref().and_then(|c| c.core_crate_override.as_deref()),
86 Language::Dart => self.dart.as_ref().and_then(|c| c.core_crate_override.as_deref()),
87 Language::Swift => self.swift.as_ref().and_then(|c| c.core_crate_override.as_deref()),
88 _ => None,
89 };
90 match override_name {
91 Some(name) => name.replace('-', "_"),
92 None => self.core_import_name(),
93 }
94 }
95
96 pub fn effective_path_mappings(&self) -> std::collections::HashMap<String, String> {
106 let mut mappings = std::collections::HashMap::new();
107
108 if self.auto_path_mappings {
109 let core_import = self.core_import_name();
110
111 for source in &self.sources {
112 let source_str = source.to_string_lossy();
113 if let Some(after_crates) = find_after_crates_prefix(&source_str) {
114 if let Some(slash_pos) = after_crates.find('/') {
115 let crate_dir = &after_crates[..slash_pos];
116 let crate_ident = crate_dir.replace('-', "_");
117 if crate_ident != core_import && !mappings.contains_key(&crate_ident) {
118 mappings.insert(crate_ident, core_import.clone());
119 }
120 }
121 }
122 }
123 }
124
125 for (from, to) in &self.path_mappings {
127 mappings.insert(from.clone(), to.clone());
128 }
129
130 mappings
131 }
132}
133
134#[cfg(test)]
135mod tests {
136 use crate::config::new_config::NewAlefConfig;
137
138 fn resolved_one(toml: &str) -> super::super::ResolvedCrateConfig {
139 let cfg: NewAlefConfig = toml::from_str(toml).unwrap();
140 cfg.resolve().unwrap().remove(0)
141 }
142
143 fn minimal() -> super::super::ResolvedCrateConfig {
144 resolved_one(
145 r#"
146[workspace]
147languages = ["python"]
148
149[[crates]]
150name = "test-lib"
151sources = ["src/lib.rs"]
152"#,
153 )
154 }
155
156 #[test]
157 fn core_import_name_defaults_to_snake_case_name() {
158 let r = minimal();
159 assert_eq!(r.core_import_name(), "test_lib");
160 }
161
162 #[test]
163 fn core_import_name_explicit_wins() {
164 let r = resolved_one(
165 r#"
166[workspace]
167languages = ["python"]
168
169[[crates]]
170name = "test-lib"
171sources = ["src/lib.rs"]
172core_import = "custom_core"
173"#,
174 );
175 assert_eq!(r.core_import_name(), "custom_core");
176 }
177
178 #[test]
179 fn error_type_name_defaults_to_error() {
180 let r = minimal();
181 assert_eq!(r.error_type_name(), "Error");
182 }
183
184 #[test]
185 fn error_type_name_explicit_wins() {
186 let r = resolved_one(
187 r#"
188[workspace]
189languages = ["python"]
190
191[[crates]]
192name = "test-lib"
193sources = ["src/lib.rs"]
194error_type = "MyError"
195"#,
196 );
197 assert_eq!(r.error_type_name(), "MyError");
198 }
199
200 #[test]
201 fn error_constructor_expr_defaults_to_from_pattern() {
202 let r = minimal();
203 assert_eq!(r.error_constructor_expr(), "test_lib::Error::from({msg})");
204 }
205
206 #[test]
207 fn error_constructor_expr_explicit_wins() {
208 let r = resolved_one(
209 r#"
210[workspace]
211languages = ["python"]
212
213[[crates]]
214name = "test-lib"
215sources = ["src/lib.rs"]
216error_constructor = "MyError::new({msg})"
217"#,
218 );
219 assert_eq!(r.error_constructor_expr(), "MyError::new({msg})");
220 }
221
222 #[test]
223 fn core_crate_dir_from_source_path() {
224 let r = resolved_one(
225 r#"
226[workspace]
227languages = ["python"]
228
229[[crates]]
230name = "test-lib"
231sources = ["crates/my-core/src/lib.rs"]
232"#,
233 );
234 assert_eq!(r.core_crate_dir(), "my-core");
235 }
236
237 #[test]
238 fn core_crate_dir_falls_back_to_name() {
239 let r = minimal();
240 assert_eq!(r.core_crate_dir(), "test-lib");
241 }
242
243 #[test]
244 fn core_crate_for_language_uses_wasm_override() {
245 use crate::config::extras::Language;
246 let r = resolved_one(
247 r#"
248[workspace]
249languages = ["wasm"]
250
251[[crates]]
252name = "test-lib"
253sources = ["src/lib.rs"]
254
255[crates.wasm]
256core_crate_override = "test-lib-wasm-core"
257"#,
258 );
259 assert_eq!(r.core_crate_for_language(Language::Wasm), "test-lib-wasm-core");
260 }
261
262 #[test]
263 fn core_import_for_language_normalizes_override_hyphens() {
264 use crate::config::extras::Language;
265 let r = resolved_one(
266 r#"
267[workspace]
268languages = ["wasm"]
269
270[[crates]]
271name = "test-lib"
272sources = ["src/lib.rs"]
273
274[crates.wasm]
275core_crate_override = "test-lib-wasm-core"
276"#,
277 );
278 assert_eq!(r.core_import_for_language(Language::Wasm), "test_lib_wasm_core");
279 }
280
281 #[test]
282 fn resolved_path_mappings_per_crate_only() {
283 let r = resolved_one(
284 r#"
285[workspace]
286languages = ["python"]
287
288[[crates]]
289name = "test-lib"
290sources = ["src/lib.rs"]
291path_mappings = { "old_mod" = "new_mod" }
292"#,
293 );
294 let mappings = r.effective_path_mappings();
295 assert_eq!(mappings.get("old_mod").map(|s| s.as_str()), Some("new_mod"));
296 }
297
298 #[test]
299 fn effective_path_mappings_auto_derives_from_sources() {
300 let r = resolved_one(
301 r#"
302[workspace]
303languages = ["python"]
304
305[[crates]]
306name = "my-lib"
307sources = ["crates/my-dep/src/lib.rs", "crates/my-lib/src/lib.rs"]
308core_import = "my_lib"
309auto_path_mappings = true
310"#,
311 );
312 let mappings = r.effective_path_mappings();
313 assert_eq!(mappings.get("my_dep").map(|s| s.as_str()), Some("my_lib"));
315 assert!(!mappings.contains_key("my_lib"));
317 }
318}