#![deny(unsafe_code)]
#![warn(rust_2018_idioms)]
#![warn(missing_docs)]
#![warn(clippy::all)]
use std::path::PathBuf;
#[cfg(not(target_arch = "wasm32"))]
use perl_uri::uri_to_fs_path;
use serde_json::Value;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct WorkspaceFolderChange {
pub added: Vec<String>,
pub removed: Vec<String>,
}
#[must_use]
pub fn workspace_folder_to_path(workspace_folder: &str) -> PathBuf {
if workspace_folder.starts_with("file://") {
#[cfg(not(target_arch = "wasm32"))]
if let Some(path) = uri_to_fs_path(workspace_folder) {
return path;
}
return PathBuf::from(workspace_folder.trim_start_matches("file://"));
}
PathBuf::from(workspace_folder)
}
#[must_use]
pub fn extract_workspace_folder_uris(workspace_folders: &[Value]) -> Vec<String> {
workspace_folders
.iter()
.filter_map(|folder| {
folder.get("uri").and_then(Value::as_str).map(std::string::ToString::to_string)
})
.collect()
}
#[must_use]
pub fn extract_workspace_folder_change(event: &Value) -> WorkspaceFolderChange {
let added = event
.get("added")
.and_then(Value::as_array)
.map_or_else(Vec::new, |entries| extract_workspace_folder_uris(entries));
let removed = event
.get("removed")
.and_then(Value::as_array)
.map_or_else(Vec::new, |entries| extract_workspace_folder_uris(entries));
WorkspaceFolderChange { added, removed }
}
#[must_use]
pub fn root_path_to_file_uri(root_path: &str) -> String {
let path = std::path::Path::new(root_path);
url::Url::from_file_path(path).map_or_else(
|_| {
if root_path.starts_with('/') {
format!("file://{}", root_path)
} else {
format!("file:///{}", root_path.replace('\\', "/"))
}
},
|uri| uri.to_string(),
)
}
#[cfg(test)]
mod tests {
use super::{
extract_workspace_folder_change, extract_workspace_folder_uris, root_path_to_file_uri,
workspace_folder_to_path,
};
use serde_json::json;
use std::path::PathBuf;
#[test]
fn parses_plain_folder_path() {
assert_eq!(workspace_folder_to_path("/tmp/project"), PathBuf::from("/tmp/project"));
}
#[cfg(not(target_arch = "wasm32"))]
#[test]
fn parses_file_uri_when_possible() {
let parsed = workspace_folder_to_path("file:///tmp/project");
assert!(parsed.to_string_lossy().contains("tmp"));
assert!(parsed.to_string_lossy().contains("project"));
}
#[test]
fn extracts_workspace_uris() {
let entries = vec![
json!({"uri": "file:///one"}),
json!({"uri": "file:///two"}),
json!({"name": "invalid"}),
];
let uris = extract_workspace_folder_uris(&entries);
assert_eq!(uris, vec!["file:///one", "file:///two"]);
}
#[test]
fn extracts_workspace_change_entries() {
let change = extract_workspace_folder_change(&json!({
"added": [{"uri": "file:///add"}],
"removed": [{"uri": "file:///remove"}],
}));
assert_eq!(change.added, vec!["file:///add"]);
assert_eq!(change.removed, vec!["file:///remove"]);
}
#[test]
fn converts_legacy_root_path_to_file_uri() {
let uri = root_path_to_file_uri("/legacy/workspace");
assert_eq!(uri, "file:///legacy/workspace");
}
}