1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
use async_tungstenite::tokio::accept_async;
use serde_json::Value;
use tokio::net::TcpListener;
use tower_lsp::jsonrpc::Result;
use tower_lsp::lsp_types::*;
use tower_lsp::{Client, LanguageServer, LspService, Server};
use tracing::info;
use ws_stream_tungstenite::*;
#[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 {
text_document_sync: Some(TextDocumentSyncCapability::Kind(
TextDocumentSyncKind::INCREMENTAL,
)),
completion_provider: Some(CompletionOptions {
resolve_provider: Some(false),
trigger_characters: Some(vec![".".to_string()]),
..Default::default()
}),
execute_command_provider: Some(ExecuteCommandOptions {
commands: vec!["dummy.do_something".to_string()],
..Default::default()
}),
workspace: Some(WorkspaceServerCapabilities {
workspace_folders: Some(WorkspaceFoldersServerCapabilities {
supported: Some(true),
change_notifications: Some(OneOf::Left(true)),
}),
..Default::default()
}),
..ServerCapabilities::default()
},
..Default::default()
})
}
async fn initialized(&self, _: InitializedParams) {
self.client
.log_message(MessageType::INFO, "initialized!")
.await;
}
async fn shutdown(&self) -> Result<()> {
Ok(())
}
async fn did_change_workspace_folders(&self, _: DidChangeWorkspaceFoldersParams) {
self.client
.log_message(MessageType::INFO, "workspace folders changed!")
.await;
}
async fn did_change_configuration(&self, _: DidChangeConfigurationParams) {
self.client
.log_message(MessageType::INFO, "configuration changed!")
.await;
}
async fn did_change_watched_files(&self, _: DidChangeWatchedFilesParams) {
self.client
.log_message(MessageType::INFO, "watched files have changed!")
.await;
}
async fn execute_command(&self, _: ExecuteCommandParams) -> Result<Option<Value>> {
self.client
.log_message(MessageType::INFO, "command executed!")
.await;
match self.client.apply_edit(WorkspaceEdit::default()).await {
Ok(res) if res.applied => self.client.log_message(MessageType::INFO, "applied").await,
Ok(_) => self.client.log_message(MessageType::INFO, "rejected").await,
Err(err) => self.client.log_message(MessageType::ERROR, err).await,
}
Ok(None)
}
async fn did_open(&self, _: DidOpenTextDocumentParams) {
self.client
.log_message(MessageType::INFO, "file opened!")
.await;
}
async fn did_change(&self, _: DidChangeTextDocumentParams) {
self.client
.log_message(MessageType::INFO, "file changed!")
.await;
}
async fn did_save(&self, _: DidSaveTextDocumentParams) {
self.client
.log_message(MessageType::INFO, "file saved!")
.await;
}
async fn did_close(&self, _: DidCloseTextDocumentParams) {
self.client
.log_message(MessageType::INFO, "file closed!")
.await;
}
async fn completion(&self, _: CompletionParams) -> Result<Option<CompletionResponse>> {
Ok(Some(CompletionResponse::Array(vec![
CompletionItem::new_simple("Hello".to_string(), "Some detail".to_string()),
CompletionItem::new_simple("Bye".to_string(), "More detail".to_string()),
])))
}
}
#[tokio::main]
async fn main() {
#[cfg(feature = "runtime-agnostic")]
use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt};
tracing_subscriber::fmt().init();
let listener = TcpListener::bind("127.0.0.1:9257").await.unwrap();
info!("Listening on {}", listener.local_addr().unwrap());
let (stream, _) = listener.accept().await.unwrap();
let (read, write) = tokio::io::split(WsStream::new(accept_async(stream).await.unwrap()));
#[cfg(feature = "runtime-agnostic")]
let (read, write) = (read.compat(), write.compat_write());
let (service, socket) = LspService::new(|client| Backend { client });
Server::new(read, write, socket).serve(service).await;
}
|