1use super::*;
2
3#[derive(Debug, PartialEq)]
4pub struct Module {
5 pub name: TextNode,
6 pub optional: bool,
7 pub path: Option<TextNode>,
8 pub range: lsp::Range,
9}
10
11impl Module {
12 #[must_use]
13 pub fn resolve(&self, base_uri: &lsp::Url) -> Option<PathBuf> {
14 let base_dir = base_uri.to_file_path().ok()?.parent()?.to_path_buf();
15
16 if let Some(path_node) = &self.path {
17 let raw = path_node.value.trim_matches(|c| c == '\'' || c == '"');
18
19 if raw.is_empty() {
20 return None;
21 }
22
23 return Some(match raw.strip_prefix("~/") {
24 Some(rest) => dirs::home_dir()?.join(rest),
25 None => base_dir.join(raw),
26 });
27 }
28
29 let name = &self.name.value;
30
31 [
32 base_dir.join(format!("{name}.just")),
33 base_dir.join(name).join("mod.just"),
34 base_dir.join(name).join("justfile"),
35 ]
36 .into_iter()
37 .find(|path| path.is_file())
38 }
39}
40
41#[cfg(test)]
42mod tests {
43 use {super::*, tempfile::Builder};
44
45 fn module(name: &str, path: Option<&str>) -> Module {
46 Module {
47 name: TextNode {
48 value: name.to_owned(),
49 range: lsp::Range::default(),
50 },
51 optional: false,
52 path: path.map(|p| TextNode {
53 value: p.to_owned(),
54 range: lsp::Range::default(),
55 }),
56 range: lsp::Range::default(),
57 }
58 }
59
60 #[test]
61 fn explicit_path() {
62 let directory = Builder::new().prefix("just-lsp").tempdir().unwrap();
63
64 let base =
65 lsp::Url::from_file_path(directory.path().join("justfile")).unwrap();
66
67 let expected = directory.path().join("bar.just");
68
69 assert_eq!(
70 module("foo", Some("'bar.just'")).resolve(&base).unwrap(),
71 expected,
72 );
73
74 assert_eq!(
75 module("foo", Some("\"bar.just\"")).resolve(&base).unwrap(),
76 expected,
77 );
78 }
79
80 #[test]
81 fn explicit_path_home_directory() {
82 let directory = Builder::new().prefix("just-lsp").tempdir().unwrap();
83
84 let base =
85 lsp::Url::from_file_path(directory.path().join("justfile")).unwrap();
86
87 assert_eq!(
88 module("foo", Some("'~/bar.just'")).resolve(&base).unwrap(),
89 dirs::home_dir().unwrap().join("bar.just"),
90 );
91 }
92
93 #[test]
94 fn empty_explicit_path_returns_none() {
95 let directory = Builder::new().prefix("just-lsp").tempdir().unwrap();
96
97 let base =
98 lsp::Url::from_file_path(directory.path().join("justfile")).unwrap();
99
100 assert_eq!(module("foo", Some("''")).resolve(&base), None);
101 assert_eq!(module("foo", Some("\"\"")).resolve(&base), None);
102 }
103
104 #[test]
105 fn implicit_mod_just() {
106 let directory = Builder::new().prefix("just-lsp").tempdir().unwrap();
107
108 std::fs::create_dir(directory.path().join("foo")).unwrap();
109 std::fs::write(directory.path().join("foo/mod.just"), "").unwrap();
110
111 let base =
112 lsp::Url::from_file_path(directory.path().join("justfile")).unwrap();
113
114 assert_eq!(
115 module("foo", None).resolve(&base).unwrap(),
116 directory.path().join("foo/mod.just"),
117 );
118 }
119
120 #[test]
121 fn implicit_justfile() {
122 let directory = Builder::new().prefix("just-lsp").tempdir().unwrap();
123
124 std::fs::create_dir(directory.path().join("foo")).unwrap();
125 std::fs::write(directory.path().join("foo/justfile"), "").unwrap();
126
127 let base =
128 lsp::Url::from_file_path(directory.path().join("justfile")).unwrap();
129
130 assert_eq!(
131 module("foo", None).resolve(&base).unwrap(),
132 directory.path().join("foo/justfile"),
133 );
134 }
135
136 #[test]
137 fn implicit_prefers_name_dot_just() {
138 let directory = Builder::new().prefix("just-lsp").tempdir().unwrap();
139
140 std::fs::write(directory.path().join("foo.just"), "").unwrap();
141 std::fs::create_dir(directory.path().join("foo")).unwrap();
142 std::fs::write(directory.path().join("foo/mod.just"), "").unwrap();
143
144 let base =
145 lsp::Url::from_file_path(directory.path().join("justfile")).unwrap();
146
147 assert_eq!(
148 module("foo", None).resolve(&base).unwrap(),
149 directory.path().join("foo.just"),
150 );
151 }
152
153 #[test]
154 fn implicit_no_file_returns_none() {
155 let directory = Builder::new().prefix("just-lsp").tempdir().unwrap();
156
157 let base =
158 lsp::Url::from_file_path(directory.path().join("justfile")).unwrap();
159
160 assert_eq!(module("foo", None).resolve(&base), None);
161 }
162}