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