use crate::types::InitializeParams;
use dashmap::DashMap;
use oak_resolver::{GlobalSymbolTable, StandardResolver};
use std::path::PathBuf;
use url::Url;
pub struct WorkspaceManager {
folders: DashMap<String, PathBuf>,
pub symbols: GlobalSymbolTable,
pub resolver: StandardResolver,
}
impl WorkspaceManager {
pub fn new() -> Self {
Self { folders: DashMap::new(), symbols: GlobalSymbolTable::new(), resolver: StandardResolver::new(Vec::new()) }
}
pub fn initialize(&self, params: &InitializeParams) {
let mut root_dirs = Vec::new();
if let Some(uri_str) = ¶ms.root_uri {
if let Ok(uri) = Url::parse(uri_str) {
if let Ok(path) = uri.to_file_path() {
self.folders.insert(uri_str.clone(), path.clone());
root_dirs.push(path);
}
}
}
for folder in ¶ms.workspace_folders {
if let Ok(uri) = Url::parse(&folder.uri) {
if let Ok(path) = uri.to_file_path() {
self.folders.insert(folder.uri.clone(), path.clone());
root_dirs.push(path);
}
}
}
self.resolver.set_root_dirs(root_dirs);
}
pub fn add_folder(&self, uri: String, _name: String) {
if let Ok(url) = Url::parse(&uri) {
if let Ok(path) = url.to_file_path() {
self.folders.insert(uri, path);
}
}
}
pub fn remove_folder(&self, uri: &str) {
self.folders.remove(uri);
}
pub fn get_path(&self, uri: &str) -> Option<PathBuf> {
if let Ok(url) = Url::parse(uri) {
if let Ok(path) = url.to_file_path() {
return Some(path);
}
}
None
}
pub fn path_to_uri(&self, path: PathBuf) -> Option<String> {
Url::from_file_path(path).ok().map(|url| url.to_string())
}
pub fn find_root(&self, uri: &str) -> Option<String> {
let path = self.get_path(uri)?;
let mut best_match: Option<(String, usize)> = None;
for entry in self.folders.iter() {
let folder_uri = entry.key();
let folder_path = entry.value();
if path.starts_with(folder_path) {
let len = folder_path.as_os_str().len();
if best_match.as_ref().map_or(true, |(_, best_len)| len > *best_len) {
best_match = Some((folder_uri.clone(), len));
}
}
}
best_match.map(|(uri, _)| uri)
}
pub fn is_within_workspace(&self, uri: &str) -> bool {
self.find_root(uri).is_some()
}
pub fn list_folders(&self) -> Vec<(String, PathBuf)> {
self.folders.iter().map(|entry| (entry.key().clone(), entry.value().clone())).collect()
}
}
impl Default for WorkspaceManager {
fn default() -> Self {
Self::new()
}
}