argyph_graph/resolve/
rust.rs1use camino::Utf8Path;
2
3use super::{ImportResolver, ModuleTarget};
4use crate::edge::Confidence;
5
6pub struct RustResolver;
7
8impl ImportResolver for RustResolver {
9 fn resolve_import(
10 &self,
11 _source_file: &Utf8Path,
12 module_path: &[String],
13 _raw: &str,
14 ) -> Option<ModuleTarget> {
15 if module_path.is_empty() {
16 return None;
17 }
18
19 let path_str = module_path.join("/");
20 let mut replaced = path_str.replace("::", "/");
21
22 if let Some(rest) = replaced.strip_prefix("crate/") {
23 replaced = rest.to_string();
24 }
25
26 let candidate = format!("src/{replaced}.rs");
27 Some(ModuleTarget {
28 file_path: candidate,
29 confidence: Confidence::Heuristic,
30 })
31 }
32}
33
34#[cfg(test)]
35#[allow(clippy::unwrap_used, clippy::expect_used)]
36mod tests {
37 use super::*;
38 use camino::Utf8Path;
39
40 #[test]
41 fn resolve_crate_module() {
42 let resolver = RustResolver;
43 let tgt = resolver
44 .resolve_import(
45 Utf8Path::new("src/main.rs"),
46 &["crate", "math", "add"]
47 .iter()
48 .map(|s| s.to_string())
49 .collect::<Vec<_>>(),
50 "use crate::math::add;",
51 )
52 .expect("should resolve crate::math::add");
53 assert_eq!(tgt.file_path, "src/math/add.rs");
54 assert_eq!(tgt.confidence, Confidence::Heuristic);
55 }
56
57 #[test]
58 fn resolve_rust_module_path() {
59 let resolver = RustResolver;
60 let tgt = resolver
61 .resolve_import(
62 Utf8Path::new("src/lib.rs"),
63 &["foo", "bar", "Baz"]
64 .iter()
65 .map(|s| s.to_string())
66 .collect::<Vec<_>>(),
67 "use foo::bar::Baz;",
68 )
69 .expect("should resolve foo::bar::Baz");
70 assert_eq!(tgt.file_path, "src/foo/bar/Baz.rs");
71 }
72}