use serde::{Deserialize, Serialize};
use serde_json::Value;
use tower_lsp::jsonrpc::{Error, Result};
use tower_lsp::lsp_types::notification::Notification;
use tower_lsp::lsp_types::*;
use tower_lsp::{Client, LanguageServer, LspService, Server};
#[derive(Debug, Deserialize, Serialize)]
struct CustomNotificationParams {
title: String,
message: String,
}
impl CustomNotificationParams {
fn new(title: impl Into<String>, message: impl Into<String>) -> Self {
CustomNotificationParams {
title: title.into(),
message: message.into(),
}
}
}
enum CustomNotification {}
impl Notification for CustomNotification {
type Params = CustomNotificationParams;
const METHOD: &'static str = "custom/notification";
}
#[derive(Debug)]
struct Backend {
client: Client,
}
#[tower_lsp::async_trait]
impl LanguageServer for Backend {
async fn initialize(&self, _: InitializeParams) -> Result<InitializeResult> {
Ok(InitializeResult {
server_info: None,
capabilities: ServerCapabilities {
execute_command_provider: Some(ExecuteCommandOptions {
commands: vec!["custom.notification".to_string()],
work_done_progress_options: Default::default(),
}),
..ServerCapabilities::default()
},
..Default::default()
})
}
async fn shutdown(&self) -> Result<()> {
Ok(())
}
async fn execute_command(&self, params: ExecuteCommandParams) -> Result<Option<Value>> {
if params.command == "custom.notification" {
self.client
.send_notification::<CustomNotification>(CustomNotificationParams::new(
"Hello", "Message",
))
.await;
self.client
.log_message(
MessageType::INFO,
format!("Command executed with params: {params:?}"),
)
.await;
Ok(None)
} else {
Err(Error::invalid_request())
}
}
}
#[tokio::main]
async fn main() {
#[cfg(feature = "runtime-agnostic")]
use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt};
tracing_subscriber::fmt().init();
let (stdin, stdout) = (tokio::io::stdin(), tokio::io::stdout());
#[cfg(feature = "runtime-agnostic")]
let (stdin, stdout) = (stdin.compat(), stdout.compat_write());
let (service, socket) = LspService::new(|client| Backend { client });
Server::new(stdin, stdout, socket).serve(service).await;
}