Skip to main content

just_lsp/
module.rs

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}