From 831fa544fcea4d615f5bb7911ce0a66322225c0b Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Sun, 24 May 2026 07:01:53 +0200 Subject: [PATCH] Pending --- crates/analyzer/src/lib.rs | 41 ++++++++------------ crates/analyzer/src/rust_analyzer.rs | 57 +++++++++++++++++++++------- 2 files changed, 59 insertions(+), 39 deletions(-) diff --git a/crates/analyzer/src/lib.rs b/crates/analyzer/src/lib.rs index e7457f8..8fa5bcb 100644 --- a/crates/analyzer/src/lib.rs +++ b/crates/analyzer/src/lib.rs @@ -7,10 +7,9 @@ use std::fs; use std::path::{Component, PathBuf}; use std::sync::Arc; -use serde_json::Value; +use lsp_types::request::GotoDefinition; use tokio::sync::Mutex; use tower_lsp::jsonrpc::Result; -use tower_lsp::lsp_types::request::Request; use tower_lsp::lsp_types::*; use tower_lsp::{Client, LanguageServer, LspService, Server}; @@ -237,37 +236,29 @@ impl LanguageServer for Backend { .log_message(MessageType::INFO, format!("Found at {position}")) .await; - self.rust_analyzer + let res = self + .rust_analyzer .lock() .await - .send( - request::GotoDefinition::METHOD, - lsp_types::GotoDefinitionParams { - text_document_position_params: lsp_types::TextDocumentPositionParams { - position: lsp_types::Position { - line: line as u32, - character: character as u32, - }, - text_document: lsp_types::TextDocumentIdentifier { - uri: Url::from_file_path(from_mist_to_rust(file_path)) - .expect("failed to generate rs url"), - }, + .request::(lsp_types::GotoDefinitionParams { + text_document_position_params: lsp_types::TextDocumentPositionParams { + position: lsp_types::Position { + line: line as u32, + character: character as u32, + }, + text_document: lsp_types::TextDocumentIdentifier { + uri: Url::from_file_path(from_mist_to_rust(file_path)) + .expect("failed to generate rs url"), }, - partial_result_params: lsp_types::PartialResultParams::default(), - work_done_progress_params: lsp_types::WorkDoneProgressParams::default(), }, - ) + partial_result_params: lsp_types::PartialResultParams::default(), + work_done_progress_params: lsp_types::WorkDoneProgressParams::default(), + }) .await .expect("Failed to send to rust"); self.client - .log_message( - MessageType::INFO, - format!( - "{:?}", - self.rust_analyzer.lock().await.read::().await - ), - ) + .log_message(MessageType::INFO, format!("{:?}", res)) .await; Ok(None) diff --git a/crates/analyzer/src/rust_analyzer.rs b/crates/analyzer/src/rust_analyzer.rs index b26e789..323de0e 100644 --- a/crates/analyzer/src/rust_analyzer.rs +++ b/crates/analyzer/src/rust_analyzer.rs @@ -1,4 +1,4 @@ -use std::{path::PathBuf, process::Stdio}; +use std::{collections::HashMap, path::PathBuf, process::Stdio, sync::Arc}; use lsp_types::{ ClientCapabilities, InitializeParams, InitializedParams, Url, WorkspaceFolder, @@ -6,15 +6,16 @@ use lsp_types::{ request::{self, Request}, }; use serde::{Deserialize, Serialize}; -use serde_json::json; -use tokio::io::{AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader}; +use serde_json::{Value, json}; +use tokio::{ + io::{AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader}, + sync::{Mutex, mpsc::Sender}, +}; #[derive(Deserialize)] pub struct JsonRpcResponse { pub jsonrpc: String, - // id can be a number or null, so we use serde_json::Value to be safe - pub id: serde_json::Value, - // We only unpack the result if it exists + pub id: Option, pub result: Option, pub error: Option, } @@ -29,7 +30,8 @@ pub struct JsonRpcError { #[derive(Debug)] pub struct RustAnalyzer { stdin: tokio::process::ChildStdin, - stdout: BufReader, + stdout: Arc>>, + pending: Arc>>>, id: usize, } @@ -82,11 +84,12 @@ impl RustAnalyzer { .spawn()?; let stdin = child.stdin.take().unwrap(); - let stdout = BufReader::new(child.stdout.take().unwrap()); + let stdout = Arc::new(Mutex::new(BufReader::new(child.stdout.take().unwrap()))); Ok(Self { stdin, stdout, + pending: Arc::new(Mutex::new(HashMap::new())), id: 0, }) } @@ -95,11 +98,11 @@ impl RustAnalyzer { &mut self, params: R::Params, ) -> Result> { - self.send(R::METHOD, params).await?; - self.read().await + let id = self.send(R::METHOD, params).await?; + self.read(id).await } - pub async fn send(&mut self, method: &str, req: T) -> std::io::Result<()> { + pub async fn send(&mut self, method: &str, req: T) -> std::io::Result { let id = { self.id += 1; self.id @@ -114,14 +117,40 @@ impl RustAnalyzer { "params": req, }), ) - .await + .await?; + + Ok(id) } - pub async fn read(&mut self) -> Result> + pub async fn read(&mut self, id: usize) -> Result> where T: for<'de> serde::Deserialize<'de>, { - let raw_string = read_lsp_message(&mut self.stdout).await?; + let (tx, mut rx) = tokio::sync::mpsc::channel(16); + + self.pending.lock().await.insert(id, tx); + + if self.pending.lock().await.len() == 1 { + let stdout = self.stdout.clone(); + let pending = self.pending.clone(); + + tokio::spawn(async move { + let raw_string = read_lsp_message(&mut *stdout.lock().await).await.unwrap(); + + let envelope: JsonRpcResponse = serde_json::from_str(&raw_string).unwrap(); + + pending + .lock() + .await + .get(&envelope.id.unwrap()) + .unwrap() + .send(raw_string) + .await + .unwrap(); + }); + } + + let raw_string = rx.recv().await.expect("Failed to receive"); let envelope: JsonRpcResponse = serde_json::from_str(&raw_string)?;