1use crate::types::InitializeParams;
2use dashmap::DashMap;
3use std::path::PathBuf;
4use url::Url;
5
6pub struct WorkspaceManager {
8 folders: DashMap<String, PathBuf>,
9}
10
11impl WorkspaceManager {
12 pub fn new() -> Self {
13 Self { folders: DashMap::new() }
14 }
15
16 pub fn initialize(&self, params: &InitializeParams) {
18 if let Some(uri_str) = ¶ms.root_uri {
19 if let Ok(uri) = Url::parse(uri_str) {
20 if let Ok(path) = uri.to_file_path() {
21 self.folders.insert(uri_str.clone(), path);
22 }
23 }
24 }
25
26 for folder in ¶ms.workspace_folders {
27 if let Ok(uri) = Url::parse(&folder.uri) {
28 if let Ok(path) = uri.to_file_path() {
29 self.folders.insert(folder.uri.clone(), path);
30 }
31 }
32 }
33 }
34
35 pub fn add_folder(&self, uri: String, _name: String) {
37 if let Ok(url) = Url::parse(&uri) {
38 if let Ok(path) = url.to_file_path() {
39 self.folders.insert(uri, path);
40 }
41 }
42 }
43
44 pub fn remove_folder(&self, uri: &str) {
46 self.folders.remove(uri);
47 }
48
49 pub fn get_path(&self, uri: &str) -> Option<PathBuf> {
51 if let Ok(url) = Url::parse(uri) {
52 if let Ok(path) = url.to_file_path() {
53 return Some(path);
54 }
55 }
56 None
57 }
58
59 pub fn path_to_uri(&self, path: PathBuf) -> Option<String> {
61 Url::from_file_path(path).ok().map(|url| url.to_string())
62 }
63
64 pub fn find_root(&self, uri: &str) -> Option<String> {
66 let path = self.get_path(uri)?;
67 let mut best_match: Option<(String, usize)> = None;
68
69 for entry in self.folders.iter() {
70 let folder_uri = entry.key();
71 let folder_path = entry.value();
72
73 if path.starts_with(folder_path) {
74 let len = folder_path.as_os_str().len();
75 if best_match.as_ref().map_or(true, |(_, best_len)| len > *best_len) {
76 best_match = Some((folder_uri.clone(), len));
77 }
78 }
79 }
80
81 best_match.map(|(uri, _)| uri)
82 }
83
84 pub fn is_within_workspace(&self, uri: &str) -> bool {
86 self.find_root(uri).is_some()
87 }
88
89 pub fn list_folders(&self) -> Vec<(String, PathBuf)> {
91 self.folders.iter().map(|entry| (entry.key().clone(), entry.value().clone())).collect()
92 }
93}
94
95impl Default for WorkspaceManager {
96 fn default() -> Self {
97 Self::new()
98 }
99}