perl_module_resolution_uri/
lib.rs1#![deny(unsafe_code)]
7#![warn(rust_2018_idioms)]
8#![warn(missing_docs)]
9#![warn(clippy::all)]
10
11use perl_module_path::module_name_to_path;
12use perl_path_security::validate_workspace_path;
13use perl_workspace_folder::workspace_folder_to_path;
14use std::path::PathBuf;
15use std::time::{Duration, Instant};
16use url::Url;
17
18#[derive(Debug, Clone, PartialEq, Eq)]
20pub enum ModuleUriResolution {
21 Resolved(String),
23 NotFound,
25 TimedOut,
27}
28
29#[must_use]
39pub fn resolve_module_uri(
40 module_name: &str,
41 open_document_uris: &[String],
42 workspace_folders: &[String],
43 include_paths: &[String],
44 use_system_inc: bool,
45 system_inc: &[PathBuf],
46 timeout: Duration,
47) -> ModuleUriResolution {
48 let start_time = Instant::now();
49 let relative_path = module_name_to_path(module_name);
50
51 for uri in open_document_uris {
52 if uri.ends_with(&relative_path) {
53 return ModuleUriResolution::Resolved(uri.clone());
54 }
55 }
56
57 for workspace_folder in workspace_folders {
58 if start_time.elapsed() > timeout {
59 return ModuleUriResolution::TimedOut;
60 }
61
62 let workspace_path = workspace_folder_to_path(workspace_folder);
63
64 for include_path in include_paths {
65 if start_time.elapsed() > timeout {
66 return ModuleUriResolution::TimedOut;
67 }
68
69 let full_path = if include_path == "." {
70 workspace_path.join(&relative_path)
71 } else {
72 workspace_path.join(include_path).join(&relative_path)
73 };
74
75 let full_path = match validate_workspace_path(&full_path, &workspace_path) {
76 Ok(path) => path,
77 Err(_) => continue,
78 };
79
80 if full_path.is_file()
81 && let Ok(url) = Url::from_file_path(&full_path)
82 {
83 return ModuleUriResolution::Resolved(url.to_string());
84 }
85 }
86 }
87
88 if use_system_inc {
89 for inc_path in system_inc {
90 if start_time.elapsed() > timeout {
91 return ModuleUriResolution::TimedOut;
92 }
93
94 let full_path = inc_path.join(&relative_path);
95 if full_path.is_file()
96 && let Ok(url) = Url::from_file_path(&full_path)
97 {
98 return ModuleUriResolution::Resolved(url.to_string());
99 }
100 }
101 }
102
103 ModuleUriResolution::NotFound
104}