Skip to main content

argyph_graph/resolve/
mod.rs

1use camino::Utf8Path;
2
3pub mod python;
4pub mod rust;
5pub mod typescript;
6
7pub trait ImportResolver {
8    fn resolve_import(
9        &self,
10        source_file: &Utf8Path,
11        module_path: &[String],
12        raw: &str,
13    ) -> Option<ModuleTarget>;
14}
15
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct ModuleTarget {
18    pub file_path: String,
19    pub confidence: super::edge::Confidence,
20}
21
22pub(crate) fn normalize_path(path: &str) -> String {
23    let is_absolute = path.starts_with('/');
24    let parts: Vec<&str> = path.split('/').filter(|p| !p.is_empty()).collect();
25    let mut out: Vec<&str> = Vec::new();
26    for part in parts {
27        if part == "." {
28            continue;
29        }
30        if part == ".." {
31            out.pop();
32        } else {
33            out.push(part);
34        }
35    }
36    let result = out.join("/");
37    if is_absolute {
38        format!("/{result}")
39    } else {
40        result
41    }
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47
48    #[test]
49    fn normalizes_dotdot() {
50        assert_eq!(normalize_path("a/b/../c"), "a/c");
51    }
52
53    #[test]
54    fn strips_dots() {
55        assert_eq!(normalize_path("a/./b"), "a/b");
56    }
57
58    #[test]
59    fn handles_multiple_dotdots() {
60        assert_eq!(normalize_path("a/b/../../c"), "c");
61    }
62
63    #[test]
64    fn preserves_absolute_path() {
65        assert_eq!(normalize_path("/a/b/../c"), "/a/c");
66    }
67}