#![allow(dead_code)]
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
use async_trait::async_trait;
use tower_lsp_server::ls_types::{Diagnostic, MessageType, Uri};
use surrealql_language_server::config::ServerSettings;
use surrealql_language_server::core::{
LanguageServerCore, LspNotifier, MetadataProvider, WorkspaceLoader,
};
use surrealql_language_server::semantic::types::{LiveMetadataSnapshot, WorkspaceIndex};
#[derive(Default)]
pub struct Recorded {
pub published: Vec<(Uri, Vec<Diagnostic>)>,
pub logs: Vec<(MessageType, String)>,
pub shows: Vec<(MessageType, String)>,
}
#[derive(Clone, Default)]
pub struct RecordingNotifier {
recorded: Arc<Mutex<Recorded>>,
pub configuration: Arc<Mutex<Option<serde_json::Value>>>,
}
impl RecordingNotifier {
pub fn recorded(&self) -> Arc<Mutex<Recorded>> {
Arc::clone(&self.recorded)
}
pub fn published(&self) -> Vec<(Uri, Vec<Diagnostic>)> {
self.recorded.lock().unwrap().published.clone()
}
pub fn logs(&self) -> Vec<(MessageType, String)> {
self.recorded.lock().unwrap().logs.clone()
}
pub fn shows(&self) -> Vec<(MessageType, String)> {
self.recorded.lock().unwrap().shows.clone()
}
pub fn last_published_for(&self, uri: &Uri) -> Option<Vec<Diagnostic>> {
self.recorded
.lock()
.unwrap()
.published
.iter()
.rev()
.find(|(published_uri, _)| published_uri == uri)
.map(|(_, diagnostics)| diagnostics.clone())
}
}
#[async_trait]
impl LspNotifier for RecordingNotifier {
async fn publish_diagnostics(&self, uri: Uri, diagnostics: Vec<Diagnostic>) {
self.recorded
.lock()
.unwrap()
.published
.push((uri, diagnostics));
}
async fn log_message(&self, level: MessageType, message: String) {
self.recorded.lock().unwrap().logs.push((level, message));
}
async fn show_message(&self, level: MessageType, message: String) {
self.recorded.lock().unwrap().shows.push((level, message));
}
async fn request_configuration(&self) -> Option<serde_json::Value> {
self.configuration.lock().unwrap().clone()
}
}
#[derive(Default)]
pub struct StaticWorkspace {
pub index: WorkspaceIndex,
}
#[async_trait]
impl WorkspaceLoader for StaticWorkspace {
async fn load(&self, _folders: &[PathBuf]) -> WorkspaceIndex {
self.index.clone()
}
async fn read_document(&self, _uri: &Uri) -> Option<String> {
None
}
}
#[derive(Clone, Default)]
pub struct RecordingMetadata {
pub snapshot: Arc<Mutex<LiveMetadataSnapshot>>,
pub last_settings: Arc<Mutex<Option<ServerSettings>>>,
}
#[async_trait]
impl MetadataProvider for RecordingMetadata {
async fn fetch(&self, settings: &ServerSettings) -> LiveMetadataSnapshot {
*self.last_settings.lock().unwrap() = Some(settings.clone());
self.snapshot.lock().unwrap().clone()
}
}
pub type TestCore = LanguageServerCore<RecordingNotifier, StaticWorkspace, RecordingMetadata>;
pub fn core_with(
workspace: WorkspaceIndex,
metadata: LiveMetadataSnapshot,
) -> (TestCore, RecordingNotifier, RecordingMetadata) {
let notifier = RecordingNotifier::default();
let provider = RecordingMetadata {
snapshot: Arc::new(Mutex::new(metadata)),
last_settings: Arc::new(Mutex::new(None)),
};
let core = LanguageServerCore::new(
notifier.clone(),
StaticWorkspace { index: workspace },
provider.clone(),
);
(core, notifier, provider)
}
pub fn uri(path: &str) -> Uri {
format!("file:///workspace/{path}")
.parse()
.expect("valid uri")
}