Add unique id to each lsp client/server pair
This commit is contained in:
parent
80b4a69053
commit
38cb934d8f
4 changed files with 48 additions and 15 deletions
|
@ -18,6 +18,7 @@ use tokio::{
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct Client {
|
||||
id: usize,
|
||||
_process: Child,
|
||||
server_tx: UnboundedSender<Payload>,
|
||||
request_counter: AtomicU64,
|
||||
|
@ -26,7 +27,11 @@ pub struct Client {
|
|||
}
|
||||
|
||||
impl Client {
|
||||
pub fn start(cmd: &str, args: &[String]) -> Result<(Self, UnboundedReceiver<Call>)> {
|
||||
pub fn start(
|
||||
cmd: &str,
|
||||
args: &[String],
|
||||
id: usize,
|
||||
) -> Result<(Self, UnboundedReceiver<(usize, Call)>)> {
|
||||
let process = Command::new(cmd)
|
||||
.args(args)
|
||||
.stdin(Stdio::piped())
|
||||
|
@ -43,9 +48,10 @@ impl Client {
|
|||
let reader = BufReader::new(process.stdout.take().expect("Failed to open stdout"));
|
||||
let stderr = BufReader::new(process.stderr.take().expect("Failed to open stderr"));
|
||||
|
||||
let (server_rx, server_tx) = Transport::start(reader, writer, stderr);
|
||||
let (server_rx, server_tx) = Transport::start(reader, writer, stderr, id);
|
||||
|
||||
let client = Self {
|
||||
id,
|
||||
_process: process,
|
||||
server_tx,
|
||||
request_counter: AtomicU64::new(0),
|
||||
|
@ -59,6 +65,10 @@ impl Client {
|
|||
Ok((client, server_rx))
|
||||
}
|
||||
|
||||
pub fn id(&self) -> usize {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn next_request_id(&self) -> jsonrpc::Id {
|
||||
let id = self.request_counter.fetch_add(1, Ordering::Relaxed);
|
||||
jsonrpc::Id::Num(id)
|
||||
|
|
|
@ -13,7 +13,10 @@ use helix_core::syntax::LanguageConfiguration;
|
|||
|
||||
use std::{
|
||||
collections::{hash_map::Entry, HashMap},
|
||||
sync::Arc,
|
||||
sync::{
|
||||
atomic::{AtomicUsize, Ordering},
|
||||
Arc,
|
||||
},
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -254,9 +257,10 @@ impl Notification {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct Registry {
|
||||
inner: HashMap<LanguageId, Arc<Client>>,
|
||||
inner: HashMap<LanguageId, (usize, Arc<Client>)>,
|
||||
|
||||
pub incoming: SelectAll<UnboundedReceiverStream<Call>>,
|
||||
counter: AtomicUsize,
|
||||
pub incoming: SelectAll<UnboundedReceiverStream<(usize, Call)>>,
|
||||
}
|
||||
|
||||
impl Default for Registry {
|
||||
|
@ -269,10 +273,18 @@ impl Registry {
|
|||
pub fn new() -> Self {
|
||||
Self {
|
||||
inner: HashMap::new(),
|
||||
counter: AtomicUsize::new(0),
|
||||
incoming: SelectAll::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_by_id(&mut self, id: usize) -> Option<&Client> {
|
||||
self.inner
|
||||
.values()
|
||||
.find(|(client_id, _)| client_id == &id)
|
||||
.map(|(_, client)| client.as_ref())
|
||||
}
|
||||
|
||||
pub fn get(&mut self, language_config: &LanguageConfiguration) -> Result<Arc<Client>> {
|
||||
if let Some(config) = &language_config.language_server {
|
||||
// avoid borrow issues
|
||||
|
@ -280,16 +292,17 @@ impl Registry {
|
|||
let s_incoming = &mut self.incoming;
|
||||
|
||||
match inner.entry(language_config.scope.clone()) {
|
||||
Entry::Occupied(language_server) => Ok(language_server.get().clone()),
|
||||
Entry::Occupied(entry) => Ok(entry.get().1.clone()),
|
||||
Entry::Vacant(entry) => {
|
||||
// initialize a new client
|
||||
let (mut client, incoming) = Client::start(&config.command, &config.args)?;
|
||||
let id = self.counter.fetch_add(1, Ordering::Relaxed);
|
||||
let (mut client, incoming) = Client::start(&config.command, &config.args, id)?;
|
||||
// TODO: run this async without blocking
|
||||
futures_executor::block_on(client.initialize())?;
|
||||
s_incoming.push(UnboundedReceiverStream::new(incoming));
|
||||
let client = Arc::new(client);
|
||||
|
||||
entry.insert(client.clone());
|
||||
entry.insert((id, client.clone()));
|
||||
Ok(client)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,8 @@ enum ServerMessage {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct Transport {
|
||||
client_tx: UnboundedSender<jsonrpc::Call>,
|
||||
id: usize,
|
||||
client_tx: UnboundedSender<(usize, jsonrpc::Call)>,
|
||||
client_rx: UnboundedReceiver<Payload>,
|
||||
|
||||
pending_requests: HashMap<jsonrpc::Id, Sender<Result<Value>>>,
|
||||
|
@ -48,11 +49,16 @@ impl Transport {
|
|||
server_stdout: BufReader<ChildStdout>,
|
||||
server_stdin: BufWriter<ChildStdin>,
|
||||
server_stderr: BufReader<ChildStderr>,
|
||||
) -> (UnboundedReceiver<jsonrpc::Call>, UnboundedSender<Payload>) {
|
||||
id: usize,
|
||||
) -> (
|
||||
UnboundedReceiver<(usize, jsonrpc::Call)>,
|
||||
UnboundedSender<Payload>,
|
||||
) {
|
||||
let (client_tx, rx) = unbounded_channel();
|
||||
let (tx, client_rx) = unbounded_channel();
|
||||
|
||||
let transport = Self {
|
||||
id,
|
||||
server_stdout,
|
||||
server_stdin,
|
||||
server_stderr,
|
||||
|
@ -156,7 +162,7 @@ impl Transport {
|
|||
match msg {
|
||||
ServerMessage::Output(output) => self.process_request_response(output).await?,
|
||||
ServerMessage::Call(call) => {
|
||||
self.client_tx.send(call).unwrap();
|
||||
self.client_tx.send((self.id, call)).unwrap();
|
||||
// let notification = Notification::parse(&method, params);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -109,8 +109,8 @@ impl Application {
|
|||
event = reader.next() => {
|
||||
self.handle_terminal_events(event)
|
||||
}
|
||||
Some(call) = self.editor.language_servers.incoming.next() => {
|
||||
self.handle_language_server_message(call).await
|
||||
Some((id, call)) = self.editor.language_servers.incoming.next() => {
|
||||
self.handle_language_server_message(call, id).await
|
||||
}
|
||||
Some(callback) = &mut self.callbacks.next() => {
|
||||
self.handle_language_server_callback(callback)
|
||||
|
@ -153,8 +153,12 @@ impl Application {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn handle_language_server_message(&mut self, call: helix_lsp::Call) {
|
||||
use helix_lsp::{Call, Notification};
|
||||
pub async fn handle_language_server_message(
|
||||
&mut self,
|
||||
call: helix_lsp::Call,
|
||||
server_id: usize,
|
||||
) {
|
||||
use helix_lsp::{Call, MethodCall, Notification};
|
||||
match call {
|
||||
Call::Notification(helix_lsp::jsonrpc::Notification { method, params, .. }) => {
|
||||
let notification = match Notification::parse(&method, params) {
|
||||
|
|
Loading…
Add table
Reference in a new issue