use crate::workspace::{DocumentKind, Workspace, file_path_from_uri};
use lsp_types::Uri;
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub struct Document {
pub version: i32,
pub text: String,
}
pub type Documents = HashMap<String, Document>;
#[derive(Debug, Default)]
pub struct ServerState {
pub documents: Documents,
pub document_kinds: HashMap<String, DocumentKind>,
pub workspace: Workspace,
}
impl ServerState {
pub fn new() -> Self {
Self::default()
}
pub fn with_workspace(workspace: Workspace) -> Self {
Self {
documents: Documents::new(),
document_kinds: HashMap::new(),
workspace,
}
}
pub fn set_document_kind(
&mut self,
uri: &Uri,
language_id: Option<&str>,
kind: Option<DocumentKind>,
) {
let path = file_path_from_uri(uri);
let kind = kind.unwrap_or_else(|| DocumentKind::classify(language_id, path.as_deref()));
self.document_kinds.insert(uri.as_str().to_owned(), kind);
}
pub fn remove_document_kind(&mut self, uri: &Uri) {
self.document_kinds.remove(uri.as_str());
}
pub fn document_kind(&self, uri: &Uri) -> DocumentKind {
self.document_kinds
.get(uri.as_str())
.copied()
.unwrap_or_else(|| {
let path = file_path_from_uri(uri);
DocumentKind::classify(None, path.as_deref())
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn classifies_document_kind_from_open_metadata() {
let uri = "file:///workspace/rust/Cargo.toml.tera"
.parse()
.expect("URI should parse");
let mut state = ServerState::new();
state.set_document_kind(&uri, Some("tera"), None);
assert_eq!(state.document_kind(&uri), DocumentKind::TeraTemplate);
}
#[test]
fn falls_back_to_uri_classification_for_unknown_documents() {
let uri = "file:///workspace/rust/achitekfile"
.parse()
.expect("URI should parse");
let state = ServerState::new();
assert_eq!(state.document_kind(&uri), DocumentKind::Achitekfile);
}
}