perl_module/resolution/use_lib/
resolve.rs1use std::path::{Component, Path, PathBuf};
4
5use super::UseLibPath;
6
7pub fn resolve_use_lib_paths(
13 use_lib_paths: &[UseLibPath],
14 workspace_root: &Path,
15 file_dir: Option<&Path>,
16) -> Vec<String> {
17 let mut result = Vec::new();
18
19 for ulp in use_lib_paths {
20 let path_str = &ulp.path;
21
22 if ulp.from_findbin {
23 let base = file_dir.unwrap_or(workspace_root);
24 let Some(resolved) = normalize_findbin_path(base, path_str) else {
25 continue;
26 };
27 if resolved.strip_prefix(workspace_root).is_err() {
28 continue;
29 }
30 if let Some(s) = path_to_relative_string(&resolved, workspace_root)
31 && !result.contains(&s)
32 {
33 result.push(s);
34 }
35 } else {
36 let p = Path::new(path_str);
37 if p.is_absolute() {
38 if let Some(s) = path_to_relative_string(p, workspace_root)
39 && !result.contains(&s)
40 {
41 result.push(s);
42 }
43 } else {
44 let s = path_str.to_string();
45 if !result.contains(&s) {
46 result.push(s);
47 }
48 }
49 }
50 }
51
52 result
53}
54
55fn path_to_relative_string(path: &Path, workspace_root: &Path) -> Option<String> {
56 if let Ok(rel) = path.strip_prefix(workspace_root) {
57 if rel.components().any(|c| c == std::path::Component::ParentDir) {
62 return None;
63 }
64 let s = normalize_relative_path_string(rel.to_string_lossy().as_ref());
65 if s.is_empty() { Some(".".to_string()) } else { Some(s) }
66 } else if path.is_absolute() {
67 None
68 } else {
69 let s = normalize_relative_path_string(path.to_string_lossy().as_ref());
70 Some(s)
71 }
72}
73
74fn normalize_relative_path_string(path: &str) -> String {
75 path.replace('\\', "/")
76}
77
78fn normalize_findbin_path(base: &Path, relative: &str) -> Option<PathBuf> {
79 let mut normalized = PathBuf::from(base);
80 for component in Path::new(relative).components() {
81 match component {
82 Component::CurDir => {}
83 Component::Normal(segment) => normalized.push(segment),
84 Component::ParentDir => {
85 if !normalized.pop() {
86 return None;
87 }
88 }
89 Component::RootDir | Component::Prefix(_) => return None,
90 }
91 }
92 Some(normalized)
93}