lsp.rs

   1mod input_handler;
   2
   3pub use lsp_types::request::*;
   4pub use lsp_types::*;
   5
   6use anyhow::{Context as _, Result, anyhow};
   7use collections::{BTreeMap, HashMap};
   8use futures::{
   9    AsyncRead, AsyncWrite, Future, FutureExt,
  10    channel::oneshot::{self, Canceled},
  11    io::BufWriter,
  12    select,
  13};
  14use gpui::{App, AppContext as _, AsyncApp, BackgroundExecutor, SharedString, Task};
  15use notification::DidChangeWorkspaceFolders;
  16use parking_lot::{Mutex, RwLock};
  17use postage::{barrier, prelude::Stream};
  18use schemars::JsonSchema;
  19use serde::{Deserialize, Serialize, de::DeserializeOwned};
  20use serde_json::{Value, json, value::RawValue};
  21use smol::{
  22    channel,
  23    io::{AsyncBufReadExt, AsyncWriteExt, BufReader},
  24    process::Child,
  25};
  26
  27use std::{
  28    collections::BTreeSet,
  29    ffi::{OsStr, OsString},
  30    fmt,
  31    io::Write,
  32    ops::DerefMut,
  33    path::PathBuf,
  34    pin::Pin,
  35    sync::{
  36        Arc, Weak,
  37        atomic::{AtomicI32, Ordering::SeqCst},
  38    },
  39    task::Poll,
  40    time::{Duration, Instant},
  41};
  42use std::{path::Path, process::Stdio};
  43use util::{ConnectionResult, ResultExt, TryFutureExt, redact};
  44
  45const JSON_RPC_VERSION: &str = "2.0";
  46const CONTENT_LEN_HEADER: &str = "Content-Length: ";
  47
  48pub const LSP_REQUEST_TIMEOUT: Duration = Duration::from_secs(60 * 2);
  49const SERVER_SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(5);
  50
  51type NotificationHandler = Box<dyn Send + FnMut(Option<RequestId>, Value, &mut AsyncApp)>;
  52type ResponseHandler = Box<dyn Send + FnOnce(Result<String, Error>)>;
  53type IoHandler = Box<dyn Send + FnMut(IoKind, &str)>;
  54
  55/// Kind of language server stdio given to an IO handler.
  56#[derive(Debug, Clone, Copy)]
  57pub enum IoKind {
  58    StdOut,
  59    StdIn,
  60    StdErr,
  61}
  62
  63/// Represents a launchable language server. This can either be a standalone binary or the path
  64/// to a runtime with arguments to instruct it to launch the actual language server file.
  65#[derive(Clone, Serialize)]
  66pub struct LanguageServerBinary {
  67    pub path: PathBuf,
  68    pub arguments: Vec<OsString>,
  69    pub env: Option<HashMap<String, String>>,
  70}
  71
  72/// Configures the search (and installation) of language servers.
  73#[derive(Debug, Clone)]
  74pub struct LanguageServerBinaryOptions {
  75    /// Whether the adapter should look at the users system
  76    pub allow_path_lookup: bool,
  77    /// Whether the adapter should download its own version
  78    pub allow_binary_download: bool,
  79    /// Whether the adapter should download a pre-release version
  80    pub pre_release: bool,
  81}
  82
  83struct NotificationSerializer(Box<dyn FnOnce() -> String + Send + Sync>);
  84
  85/// A running language server process.
  86pub struct LanguageServer {
  87    server_id: LanguageServerId,
  88    next_id: AtomicI32,
  89    outbound_tx: channel::Sender<String>,
  90    notification_tx: channel::Sender<NotificationSerializer>,
  91    name: LanguageServerName,
  92    version: Option<SharedString>,
  93    process_name: Arc<str>,
  94    binary: LanguageServerBinary,
  95    capabilities: RwLock<ServerCapabilities>,
  96    /// Configuration sent to the server, stored for display in the language server logs
  97    /// buffer. This is represented as the message sent to the LSP in order to avoid cloning it (can
  98    /// be large in cases like sending schemas to the json server).
  99    configuration: Arc<DidChangeConfigurationParams>,
 100    code_action_kinds: Option<Vec<CodeActionKind>>,
 101    notification_handlers: Arc<Mutex<HashMap<&'static str, NotificationHandler>>>,
 102    response_handlers: Arc<Mutex<Option<HashMap<RequestId, ResponseHandler>>>>,
 103    io_handlers: Arc<Mutex<HashMap<i32, IoHandler>>>,
 104    executor: BackgroundExecutor,
 105    #[allow(clippy::type_complexity)]
 106    io_tasks: Mutex<Option<(Task<Option<()>>, Task<Option<()>>)>>,
 107    output_done_rx: Mutex<Option<barrier::Receiver>>,
 108    server: Arc<Mutex<Option<Child>>>,
 109    workspace_folders: Option<Arc<Mutex<BTreeSet<Uri>>>>,
 110    root_uri: Uri,
 111}
 112
 113#[derive(Clone, Debug, PartialEq, Eq, Hash)]
 114pub enum LanguageServerSelector {
 115    Id(LanguageServerId),
 116    Name(LanguageServerName),
 117}
 118
 119/// Identifies a running language server.
 120#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
 121#[repr(transparent)]
 122pub struct LanguageServerId(pub usize);
 123
 124impl LanguageServerId {
 125    pub fn from_proto(id: u64) -> Self {
 126        Self(id as usize)
 127    }
 128
 129    pub fn to_proto(self) -> u64 {
 130        self.0 as u64
 131    }
 132}
 133
 134/// A name of a language server.
 135#[derive(
 136    Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize, JsonSchema,
 137)]
 138#[serde(transparent)]
 139pub struct LanguageServerName(pub SharedString);
 140
 141impl std::fmt::Display for LanguageServerName {
 142    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 143        std::fmt::Display::fmt(&self.0, f)
 144    }
 145}
 146
 147impl AsRef<str> for LanguageServerName {
 148    fn as_ref(&self) -> &str {
 149        self.0.as_ref()
 150    }
 151}
 152
 153impl AsRef<OsStr> for LanguageServerName {
 154    fn as_ref(&self) -> &OsStr {
 155        self.0.as_ref().as_ref()
 156    }
 157}
 158
 159impl LanguageServerName {
 160    pub const fn new_static(s: &'static str) -> Self {
 161        Self(SharedString::new_static(s))
 162    }
 163
 164    pub fn from_proto(s: String) -> Self {
 165        Self(s.into())
 166    }
 167}
 168
 169impl<'a> From<&'a str> for LanguageServerName {
 170    fn from(str: &'a str) -> LanguageServerName {
 171        LanguageServerName(str.to_string().into())
 172    }
 173}
 174
 175impl PartialEq<str> for LanguageServerName {
 176    fn eq(&self, other: &str) -> bool {
 177        self.0 == other
 178    }
 179}
 180
 181/// Handle to a language server RPC activity subscription.
 182pub enum Subscription {
 183    Notification {
 184        method: &'static str,
 185        notification_handlers: Option<Arc<Mutex<HashMap<&'static str, NotificationHandler>>>>,
 186    },
 187    Io {
 188        id: i32,
 189        io_handlers: Option<Weak<Mutex<HashMap<i32, IoHandler>>>>,
 190    },
 191}
 192
 193/// Language server protocol RPC request message ID.
 194///
 195/// [LSP Specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#requestMessage)
 196#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
 197#[serde(untagged)]
 198pub enum RequestId {
 199    Int(i32),
 200    Str(String),
 201}
 202
 203/// Language server protocol RPC request message.
 204///
 205/// [LSP Specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#requestMessage)
 206#[derive(Serialize, Deserialize)]
 207pub struct Request<'a, T> {
 208    jsonrpc: &'static str,
 209    id: RequestId,
 210    method: &'a str,
 211    params: T,
 212}
 213
 214/// Language server protocol RPC request response message before it is deserialized into a concrete type.
 215#[derive(Serialize, Deserialize)]
 216struct AnyResponse<'a> {
 217    jsonrpc: &'a str,
 218    id: RequestId,
 219    #[serde(default)]
 220    error: Option<Error>,
 221    #[serde(borrow)]
 222    result: Option<&'a RawValue>,
 223}
 224
 225/// Language server protocol RPC request response message.
 226///
 227/// [LSP Specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#responseMessage)
 228#[derive(Serialize)]
 229struct Response<T> {
 230    jsonrpc: &'static str,
 231    id: RequestId,
 232    #[serde(flatten)]
 233    value: LspResult<T>,
 234}
 235
 236#[derive(Serialize)]
 237#[serde(rename_all = "snake_case")]
 238enum LspResult<T> {
 239    #[serde(rename = "result")]
 240    Ok(Option<T>),
 241    Error(Option<Error>),
 242}
 243
 244/// Language server protocol RPC notification message.
 245///
 246/// [LSP Specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#notificationMessage)
 247#[derive(Serialize, Deserialize)]
 248struct Notification<'a, T> {
 249    jsonrpc: &'static str,
 250    #[serde(borrow)]
 251    method: &'a str,
 252    params: T,
 253}
 254
 255/// Language server RPC notification message before it is deserialized into a concrete type.
 256#[derive(Debug, Clone, Deserialize)]
 257struct NotificationOrRequest {
 258    #[serde(default)]
 259    id: Option<RequestId>,
 260    method: String,
 261    #[serde(default)]
 262    params: Option<Value>,
 263}
 264
 265#[derive(Debug, Serialize, Deserialize)]
 266struct Error {
 267    code: i64,
 268    message: String,
 269    #[serde(default)]
 270    data: Option<serde_json::Value>,
 271}
 272
 273pub trait LspRequestFuture<O>: Future<Output = ConnectionResult<O>> {
 274    fn id(&self) -> i32;
 275}
 276
 277struct LspRequest<F> {
 278    id: i32,
 279    request: F,
 280}
 281
 282impl<F> LspRequest<F> {
 283    pub fn new(id: i32, request: F) -> Self {
 284        Self { id, request }
 285    }
 286}
 287
 288impl<F: Future> Future for LspRequest<F> {
 289    type Output = F::Output;
 290
 291    fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
 292        // SAFETY: This is standard pin projection, we're pinned so our fields must be pinned.
 293        let inner = unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().request) };
 294        inner.poll(cx)
 295    }
 296}
 297
 298impl<F, O> LspRequestFuture<O> for LspRequest<F>
 299where
 300    F: Future<Output = ConnectionResult<O>>,
 301{
 302    fn id(&self) -> i32 {
 303        self.id
 304    }
 305}
 306
 307/// Combined capabilities of the server and the adapter.
 308#[derive(Debug)]
 309pub struct AdapterServerCapabilities {
 310    // Reported capabilities by the server
 311    pub server_capabilities: ServerCapabilities,
 312    // List of code actions supported by the LspAdapter matching the server
 313    pub code_action_kinds: Option<Vec<CodeActionKind>>,
 314}
 315
 316impl LanguageServer {
 317    /// Starts a language server process.
 318    pub fn new(
 319        stderr_capture: Arc<Mutex<Option<String>>>,
 320        server_id: LanguageServerId,
 321        server_name: LanguageServerName,
 322        binary: LanguageServerBinary,
 323        root_path: &Path,
 324        code_action_kinds: Option<Vec<CodeActionKind>>,
 325        workspace_folders: Option<Arc<Mutex<BTreeSet<Uri>>>>,
 326        cx: &mut AsyncApp,
 327    ) -> Result<Self> {
 328        let working_dir = if root_path.is_dir() {
 329            root_path
 330        } else {
 331            root_path.parent().unwrap_or_else(|| Path::new("/"))
 332        };
 333        let root_uri = Uri::from_file_path(&working_dir)
 334            .map_err(|()| anyhow!("{working_dir:?} is not a valid URI"))?;
 335        log::info!(
 336            "starting language server process. binary path: \
 337            {:?}, working directory: {:?}, args: {:?}",
 338            binary.path,
 339            working_dir,
 340            &binary.arguments
 341        );
 342        let mut command = util::command::new_smol_command(&binary.path);
 343        command
 344            .current_dir(working_dir)
 345            .args(&binary.arguments)
 346            .envs(binary.env.clone().unwrap_or_default())
 347            .stdin(Stdio::piped())
 348            .stdout(Stdio::piped())
 349            .stderr(Stdio::piped())
 350            .kill_on_drop(true);
 351
 352        let mut server = command
 353            .spawn()
 354            .with_context(|| format!("failed to spawn command {command:?}",))?;
 355
 356        let stdin = server.stdin.take().unwrap();
 357        let stdout = server.stdout.take().unwrap();
 358        let stderr = server.stderr.take().unwrap();
 359        let server = Self::new_internal(
 360            server_id,
 361            server_name,
 362            stdin,
 363            stdout,
 364            Some(stderr),
 365            stderr_capture,
 366            Some(server),
 367            code_action_kinds,
 368            binary,
 369            root_uri,
 370            workspace_folders,
 371            cx,
 372            move |notification| {
 373                log::info!(
 374                    "Language server with id {} sent unhandled notification {}:\n{}",
 375                    server_id,
 376                    notification.method,
 377                    serde_json::to_string_pretty(&notification.params).unwrap(),
 378                );
 379                false
 380            },
 381        );
 382
 383        Ok(server)
 384    }
 385
 386    fn new_internal<Stdin, Stdout, Stderr, F>(
 387        server_id: LanguageServerId,
 388        server_name: LanguageServerName,
 389        stdin: Stdin,
 390        stdout: Stdout,
 391        stderr: Option<Stderr>,
 392        stderr_capture: Arc<Mutex<Option<String>>>,
 393        server: Option<Child>,
 394        code_action_kinds: Option<Vec<CodeActionKind>>,
 395        binary: LanguageServerBinary,
 396        root_uri: Uri,
 397        workspace_folders: Option<Arc<Mutex<BTreeSet<Uri>>>>,
 398        cx: &mut AsyncApp,
 399        on_unhandled_notification: F,
 400    ) -> Self
 401    where
 402        Stdin: AsyncWrite + Unpin + Send + 'static,
 403        Stdout: AsyncRead + Unpin + Send + 'static,
 404        Stderr: AsyncRead + Unpin + Send + 'static,
 405        F: Fn(&NotificationOrRequest) -> bool + 'static + Send + Sync + Clone,
 406    {
 407        let (outbound_tx, outbound_rx) = channel::unbounded::<String>();
 408        let (output_done_tx, output_done_rx) = barrier::channel();
 409        let notification_handlers =
 410            Arc::new(Mutex::new(HashMap::<_, NotificationHandler>::default()));
 411        let response_handlers =
 412            Arc::new(Mutex::new(Some(HashMap::<_, ResponseHandler>::default())));
 413        let io_handlers = Arc::new(Mutex::new(HashMap::default()));
 414
 415        let stdout_input_task = cx.spawn({
 416            let unhandled_notification_wrapper = {
 417                let response_channel = outbound_tx.clone();
 418                async move |msg: NotificationOrRequest| {
 419                    let did_handle = on_unhandled_notification(&msg);
 420                    if !did_handle && let Some(message_id) = msg.id {
 421                        let response = AnyResponse {
 422                            jsonrpc: JSON_RPC_VERSION,
 423                            id: message_id,
 424                            error: Some(Error {
 425                                code: -32601,
 426                                message: format!("Unrecognized method `{}`", msg.method),
 427                                data: None,
 428                            }),
 429                            result: None,
 430                        };
 431                        if let Ok(response) = serde_json::to_string(&response) {
 432                            response_channel.send(response).await.ok();
 433                        }
 434                    }
 435                }
 436            };
 437            let notification_handlers = notification_handlers.clone();
 438            let response_handlers = response_handlers.clone();
 439            let io_handlers = io_handlers.clone();
 440            async move |cx| {
 441                Self::handle_incoming_messages(
 442                    stdout,
 443                    unhandled_notification_wrapper,
 444                    notification_handlers,
 445                    response_handlers,
 446                    io_handlers,
 447                    cx,
 448                )
 449                .log_err()
 450                .await
 451            }
 452        });
 453        let stderr_input_task = stderr
 454            .map(|stderr| {
 455                let io_handlers = io_handlers.clone();
 456                let stderr_captures = stderr_capture.clone();
 457                cx.background_spawn(async move {
 458                    Self::handle_stderr(stderr, io_handlers, stderr_captures)
 459                        .log_err()
 460                        .await
 461                })
 462            })
 463            .unwrap_or_else(|| Task::ready(None));
 464        let input_task = cx.background_spawn(async move {
 465            let (stdout, stderr) = futures::join!(stdout_input_task, stderr_input_task);
 466            stdout.or(stderr)
 467        });
 468        let output_task = cx.background_spawn({
 469            Self::handle_outgoing_messages(
 470                stdin,
 471                outbound_rx,
 472                output_done_tx,
 473                response_handlers.clone(),
 474                io_handlers.clone(),
 475            )
 476            .log_err()
 477        });
 478
 479        let configuration = DidChangeConfigurationParams {
 480            settings: Value::Null,
 481        }
 482        .into();
 483
 484        let (notification_tx, notification_rx) = channel::unbounded::<NotificationSerializer>();
 485        cx.background_spawn({
 486            let outbound_tx = outbound_tx.clone();
 487            async move {
 488                while let Ok(serializer) = notification_rx.recv().await {
 489                    let serialized = (serializer.0)();
 490                    let Ok(_) = outbound_tx.send(serialized).await else {
 491                        return;
 492                    };
 493                }
 494                outbound_tx.close();
 495            }
 496        })
 497        .detach();
 498        Self {
 499            server_id,
 500            notification_handlers,
 501            notification_tx,
 502            response_handlers,
 503            io_handlers,
 504            name: server_name,
 505            version: None,
 506            process_name: binary
 507                .path
 508                .file_name()
 509                .map(|name| Arc::from(name.to_string_lossy()))
 510                .unwrap_or_default(),
 511            binary,
 512            capabilities: Default::default(),
 513            configuration,
 514            code_action_kinds,
 515            next_id: Default::default(),
 516            outbound_tx,
 517            executor: cx.background_executor().clone(),
 518            io_tasks: Mutex::new(Some((input_task, output_task))),
 519            output_done_rx: Mutex::new(Some(output_done_rx)),
 520            server: Arc::new(Mutex::new(server)),
 521            workspace_folders,
 522            root_uri,
 523        }
 524    }
 525
 526    /// List of code action kinds this language server reports being able to emit.
 527    pub fn code_action_kinds(&self) -> Option<Vec<CodeActionKind>> {
 528        self.code_action_kinds.clone()
 529    }
 530
 531    async fn handle_incoming_messages<Stdout>(
 532        stdout: Stdout,
 533        on_unhandled_notification: impl AsyncFn(NotificationOrRequest) + 'static + Send,
 534        notification_handlers: Arc<Mutex<HashMap<&'static str, NotificationHandler>>>,
 535        response_handlers: Arc<Mutex<Option<HashMap<RequestId, ResponseHandler>>>>,
 536        io_handlers: Arc<Mutex<HashMap<i32, IoHandler>>>,
 537        cx: &mut AsyncApp,
 538    ) -> anyhow::Result<()>
 539    where
 540        Stdout: AsyncRead + Unpin + Send + 'static,
 541    {
 542        use smol::stream::StreamExt;
 543        let stdout = BufReader::new(stdout);
 544        let _clear_response_handlers = util::defer({
 545            let response_handlers = response_handlers.clone();
 546            move || {
 547                response_handlers.lock().take();
 548            }
 549        });
 550        let mut input_handler = input_handler::LspStdoutHandler::new(
 551            stdout,
 552            response_handlers,
 553            io_handlers,
 554            cx.background_executor().clone(),
 555        );
 556
 557        while let Some(msg) = input_handler.incoming_messages.next().await {
 558            let unhandled_message = {
 559                let mut notification_handlers = notification_handlers.lock();
 560                if let Some(handler) = notification_handlers.get_mut(msg.method.as_str()) {
 561                    handler(msg.id, msg.params.unwrap_or(Value::Null), cx);
 562                    None
 563                } else {
 564                    Some(msg)
 565                }
 566            };
 567
 568            if let Some(msg) = unhandled_message {
 569                on_unhandled_notification(msg).await;
 570            }
 571
 572            // Don't starve the main thread when receiving lots of notifications at once.
 573            smol::future::yield_now().await;
 574        }
 575        input_handler.loop_handle.await
 576    }
 577
 578    async fn handle_stderr<Stderr>(
 579        stderr: Stderr,
 580        io_handlers: Arc<Mutex<HashMap<i32, IoHandler>>>,
 581        stderr_capture: Arc<Mutex<Option<String>>>,
 582    ) -> anyhow::Result<()>
 583    where
 584        Stderr: AsyncRead + Unpin + Send + 'static,
 585    {
 586        let mut stderr = BufReader::new(stderr);
 587        let mut buffer = Vec::new();
 588
 589        loop {
 590            buffer.clear();
 591
 592            let bytes_read = stderr.read_until(b'\n', &mut buffer).await?;
 593            if bytes_read == 0 {
 594                return Ok(());
 595            }
 596
 597            if let Ok(message) = std::str::from_utf8(&buffer) {
 598                log::trace!("incoming stderr message:{message}");
 599                for handler in io_handlers.lock().values_mut() {
 600                    handler(IoKind::StdErr, message);
 601                }
 602
 603                if let Some(stderr) = stderr_capture.lock().as_mut() {
 604                    stderr.push_str(message);
 605                }
 606            }
 607
 608            // Don't starve the main thread when receiving lots of messages at once.
 609            smol::future::yield_now().await;
 610        }
 611    }
 612
 613    async fn handle_outgoing_messages<Stdin>(
 614        stdin: Stdin,
 615        outbound_rx: channel::Receiver<String>,
 616        output_done_tx: barrier::Sender,
 617        response_handlers: Arc<Mutex<Option<HashMap<RequestId, ResponseHandler>>>>,
 618        io_handlers: Arc<Mutex<HashMap<i32, IoHandler>>>,
 619    ) -> anyhow::Result<()>
 620    where
 621        Stdin: AsyncWrite + Unpin + Send + 'static,
 622    {
 623        let mut stdin = BufWriter::new(stdin);
 624        let _clear_response_handlers = util::defer({
 625            let response_handlers = response_handlers.clone();
 626            move || {
 627                response_handlers.lock().take();
 628            }
 629        });
 630        let mut content_len_buffer = Vec::new();
 631        while let Ok(message) = outbound_rx.recv().await {
 632            log::trace!("outgoing message:{}", message);
 633            for handler in io_handlers.lock().values_mut() {
 634                handler(IoKind::StdIn, &message);
 635            }
 636
 637            content_len_buffer.clear();
 638            write!(content_len_buffer, "{}", message.len()).unwrap();
 639            stdin.write_all(CONTENT_LEN_HEADER.as_bytes()).await?;
 640            stdin.write_all(&content_len_buffer).await?;
 641            stdin.write_all("\r\n\r\n".as_bytes()).await?;
 642            stdin.write_all(message.as_bytes()).await?;
 643            stdin.flush().await?;
 644        }
 645        drop(output_done_tx);
 646        Ok(())
 647    }
 648
 649    pub fn default_initialize_params(&self, pull_diagnostics: bool, cx: &App) -> InitializeParams {
 650        let workspace_folders = self.workspace_folders.as_ref().map_or_else(
 651            || {
 652                vec![WorkspaceFolder {
 653                    name: Default::default(),
 654                    uri: self.root_uri.clone(),
 655                }]
 656            },
 657            |folders| {
 658                folders
 659                    .lock()
 660                    .iter()
 661                    .cloned()
 662                    .map(|uri| WorkspaceFolder {
 663                        name: Default::default(),
 664                        uri,
 665                    })
 666                    .collect()
 667            },
 668        );
 669
 670        #[allow(deprecated)]
 671        InitializeParams {
 672            process_id: Some(std::process::id()),
 673            root_path: None,
 674            root_uri: Some(self.root_uri.clone()),
 675            initialization_options: None,
 676            capabilities: ClientCapabilities {
 677                general: Some(GeneralClientCapabilities {
 678                    position_encodings: Some(vec![PositionEncodingKind::UTF16]),
 679                    ..GeneralClientCapabilities::default()
 680                }),
 681                workspace: Some(WorkspaceClientCapabilities {
 682                    configuration: Some(true),
 683                    did_change_watched_files: Some(DidChangeWatchedFilesClientCapabilities {
 684                        dynamic_registration: Some(true),
 685                        relative_pattern_support: Some(true),
 686                    }),
 687                    did_change_configuration: Some(DynamicRegistrationClientCapabilities {
 688                        dynamic_registration: Some(true),
 689                    }),
 690                    workspace_folders: Some(true),
 691                    symbol: Some(WorkspaceSymbolClientCapabilities {
 692                        resolve_support: None,
 693                        dynamic_registration: Some(true),
 694                        ..WorkspaceSymbolClientCapabilities::default()
 695                    }),
 696                    inlay_hint: Some(InlayHintWorkspaceClientCapabilities {
 697                        refresh_support: Some(true),
 698                    }),
 699                    diagnostics: Some(DiagnosticWorkspaceClientCapabilities {
 700                        refresh_support: Some(true),
 701                    })
 702                    .filter(|_| pull_diagnostics),
 703                    code_lens: Some(CodeLensWorkspaceClientCapabilities {
 704                        refresh_support: Some(true),
 705                    }),
 706                    workspace_edit: Some(WorkspaceEditClientCapabilities {
 707                        resource_operations: Some(vec![
 708                            ResourceOperationKind::Create,
 709                            ResourceOperationKind::Rename,
 710                            ResourceOperationKind::Delete,
 711                        ]),
 712                        document_changes: Some(true),
 713                        snippet_edit_support: Some(true),
 714                        ..WorkspaceEditClientCapabilities::default()
 715                    }),
 716                    file_operations: Some(WorkspaceFileOperationsClientCapabilities {
 717                        dynamic_registration: Some(true),
 718                        did_rename: Some(true),
 719                        will_rename: Some(true),
 720                        ..WorkspaceFileOperationsClientCapabilities::default()
 721                    }),
 722                    apply_edit: Some(true),
 723                    execute_command: Some(ExecuteCommandClientCapabilities {
 724                        dynamic_registration: Some(true),
 725                    }),
 726                    ..WorkspaceClientCapabilities::default()
 727                }),
 728                text_document: Some(TextDocumentClientCapabilities {
 729                    definition: Some(GotoCapability {
 730                        link_support: Some(true),
 731                        dynamic_registration: Some(true),
 732                    }),
 733                    code_action: Some(CodeActionClientCapabilities {
 734                        code_action_literal_support: Some(CodeActionLiteralSupport {
 735                            code_action_kind: CodeActionKindLiteralSupport {
 736                                value_set: vec![
 737                                    CodeActionKind::REFACTOR.as_str().into(),
 738                                    CodeActionKind::QUICKFIX.as_str().into(),
 739                                    CodeActionKind::SOURCE.as_str().into(),
 740                                ],
 741                            },
 742                        }),
 743                        data_support: Some(true),
 744                        resolve_support: Some(CodeActionCapabilityResolveSupport {
 745                            properties: vec![
 746                                "kind".to_string(),
 747                                "diagnostics".to_string(),
 748                                "isPreferred".to_string(),
 749                                "disabled".to_string(),
 750                                "edit".to_string(),
 751                                "command".to_string(),
 752                            ],
 753                        }),
 754                        dynamic_registration: Some(true),
 755                        ..CodeActionClientCapabilities::default()
 756                    }),
 757                    completion: Some(CompletionClientCapabilities {
 758                        completion_item: Some(CompletionItemCapability {
 759                            snippet_support: Some(true),
 760                            resolve_support: Some(CompletionItemCapabilityResolveSupport {
 761                                properties: vec![
 762                                    "additionalTextEdits".to_string(),
 763                                    "command".to_string(),
 764                                    "documentation".to_string(),
 765                                    // NB: Do not have this resolved, otherwise Zed becomes slow to complete things
 766                                    // "textEdit".to_string(),
 767                                ],
 768                            }),
 769                            deprecated_support: Some(true),
 770                            tag_support: Some(TagSupport {
 771                                value_set: vec![CompletionItemTag::DEPRECATED],
 772                            }),
 773                            insert_replace_support: Some(true),
 774                            label_details_support: Some(true),
 775                            insert_text_mode_support: Some(InsertTextModeSupport {
 776                                value_set: vec![
 777                                    InsertTextMode::AS_IS,
 778                                    InsertTextMode::ADJUST_INDENTATION,
 779                                ],
 780                            }),
 781                            documentation_format: Some(vec![
 782                                MarkupKind::Markdown,
 783                                MarkupKind::PlainText,
 784                            ]),
 785                            ..CompletionItemCapability::default()
 786                        }),
 787                        insert_text_mode: Some(InsertTextMode::ADJUST_INDENTATION),
 788                        completion_list: Some(CompletionListCapability {
 789                            item_defaults: Some(vec![
 790                                "commitCharacters".to_owned(),
 791                                "editRange".to_owned(),
 792                                "insertTextMode".to_owned(),
 793                                "insertTextFormat".to_owned(),
 794                                "data".to_owned(),
 795                            ]),
 796                        }),
 797                        context_support: Some(true),
 798                        dynamic_registration: Some(true),
 799                        ..CompletionClientCapabilities::default()
 800                    }),
 801                    rename: Some(RenameClientCapabilities {
 802                        prepare_support: Some(true),
 803                        prepare_support_default_behavior: Some(
 804                            PrepareSupportDefaultBehavior::IDENTIFIER,
 805                        ),
 806                        dynamic_registration: Some(true),
 807                        ..RenameClientCapabilities::default()
 808                    }),
 809                    hover: Some(HoverClientCapabilities {
 810                        content_format: Some(vec![MarkupKind::Markdown]),
 811                        dynamic_registration: Some(true),
 812                    }),
 813                    inlay_hint: Some(InlayHintClientCapabilities {
 814                        resolve_support: Some(InlayHintResolveClientCapabilities {
 815                            properties: vec![
 816                                "textEdits".to_string(),
 817                                "tooltip".to_string(),
 818                                "label.tooltip".to_string(),
 819                                "label.location".to_string(),
 820                                "label.command".to_string(),
 821                            ],
 822                        }),
 823                        dynamic_registration: Some(true),
 824                    }),
 825                    publish_diagnostics: Some(PublishDiagnosticsClientCapabilities {
 826                        related_information: Some(true),
 827                        version_support: Some(true),
 828                        data_support: Some(true),
 829                        tag_support: Some(TagSupport {
 830                            value_set: vec![DiagnosticTag::UNNECESSARY, DiagnosticTag::DEPRECATED],
 831                        }),
 832                        code_description_support: Some(true),
 833                    }),
 834                    formatting: Some(DynamicRegistrationClientCapabilities {
 835                        dynamic_registration: Some(true),
 836                    }),
 837                    range_formatting: Some(DynamicRegistrationClientCapabilities {
 838                        dynamic_registration: Some(true),
 839                    }),
 840                    on_type_formatting: Some(DynamicRegistrationClientCapabilities {
 841                        dynamic_registration: Some(true),
 842                    }),
 843                    signature_help: Some(SignatureHelpClientCapabilities {
 844                        signature_information: Some(SignatureInformationSettings {
 845                            documentation_format: Some(vec![
 846                                MarkupKind::Markdown,
 847                                MarkupKind::PlainText,
 848                            ]),
 849                            parameter_information: Some(ParameterInformationSettings {
 850                                label_offset_support: Some(true),
 851                            }),
 852                            active_parameter_support: Some(true),
 853                        }),
 854                        dynamic_registration: Some(true),
 855                        ..SignatureHelpClientCapabilities::default()
 856                    }),
 857                    synchronization: Some(TextDocumentSyncClientCapabilities {
 858                        did_save: Some(true),
 859                        dynamic_registration: Some(true),
 860                        ..TextDocumentSyncClientCapabilities::default()
 861                    }),
 862                    code_lens: Some(CodeLensClientCapabilities {
 863                        dynamic_registration: Some(true),
 864                    }),
 865                    document_symbol: Some(DocumentSymbolClientCapabilities {
 866                        hierarchical_document_symbol_support: Some(true),
 867                        dynamic_registration: Some(true),
 868                        ..DocumentSymbolClientCapabilities::default()
 869                    }),
 870                    diagnostic: Some(DiagnosticClientCapabilities {
 871                        dynamic_registration: Some(true),
 872                        related_document_support: Some(true),
 873                    })
 874                    .filter(|_| pull_diagnostics),
 875                    color_provider: Some(DocumentColorClientCapabilities {
 876                        dynamic_registration: Some(true),
 877                    }),
 878                    ..TextDocumentClientCapabilities::default()
 879                }),
 880                experimental: Some(json!({
 881                    "serverStatusNotification": true,
 882                    "localDocs": true,
 883                })),
 884                window: Some(WindowClientCapabilities {
 885                    work_done_progress: Some(true),
 886                    show_message: Some(ShowMessageRequestClientCapabilities {
 887                        message_action_item: Some(MessageActionItemCapabilities {
 888                            additional_properties_support: Some(true),
 889                        }),
 890                    }),
 891                    ..WindowClientCapabilities::default()
 892                }),
 893            },
 894            trace: None,
 895            workspace_folders: Some(workspace_folders),
 896            client_info: release_channel::ReleaseChannel::try_global(cx).map(|release_channel| {
 897                ClientInfo {
 898                    name: release_channel.display_name().to_string(),
 899                    version: Some(release_channel::AppVersion::global(cx).to_string()),
 900                }
 901            }),
 902            locale: None,
 903            ..InitializeParams::default()
 904        }
 905    }
 906
 907    /// Initializes a language server by sending the `Initialize` request.
 908    /// Note that `options` is used directly to construct [`InitializeParams`], which is why it is owned.
 909    ///
 910    /// [LSP Specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initialize)
 911    pub fn initialize(
 912        mut self,
 913        params: InitializeParams,
 914        configuration: Arc<DidChangeConfigurationParams>,
 915        cx: &App,
 916    ) -> Task<Result<Arc<Self>>> {
 917        cx.background_spawn(async move {
 918            let response = self
 919                .request::<request::Initialize>(params)
 920                .await
 921                .into_response()
 922                .with_context(|| {
 923                    format!(
 924                        "initializing server {}, id {}",
 925                        self.name(),
 926                        self.server_id()
 927                    )
 928                })?;
 929            if let Some(info) = response.server_info {
 930                self.version = info.version.map(SharedString::from);
 931                self.process_name = info.name.into();
 932            }
 933            self.capabilities = RwLock::new(response.capabilities);
 934            self.configuration = configuration;
 935
 936            self.notify::<notification::Initialized>(InitializedParams {})?;
 937            Ok(Arc::new(self))
 938        })
 939    }
 940
 941    /// Sends a shutdown request to the language server process and prepares the [`LanguageServer`] to be dropped.
 942    pub fn shutdown(&self) -> Option<impl 'static + Send + Future<Output = Option<()>> + use<>> {
 943        if let Some(tasks) = self.io_tasks.lock().take() {
 944            let response_handlers = self.response_handlers.clone();
 945            let next_id = AtomicI32::new(self.next_id.load(SeqCst));
 946            let outbound_tx = self.outbound_tx.clone();
 947            let executor = self.executor.clone();
 948            let notification_serializers = self.notification_tx.clone();
 949            let mut output_done = self.output_done_rx.lock().take().unwrap();
 950            let shutdown_request = Self::request_internal::<request::Shutdown>(
 951                &next_id,
 952                &response_handlers,
 953                &outbound_tx,
 954                &notification_serializers,
 955                &executor,
 956                (),
 957            );
 958
 959            let server = self.server.clone();
 960            let name = self.name.clone();
 961            let server_id = self.server_id;
 962            let mut timer = self.executor.timer(SERVER_SHUTDOWN_TIMEOUT).fuse();
 963            Some(async move {
 964                log::debug!("language server shutdown started");
 965
 966                select! {
 967                    request_result = shutdown_request.fuse() => {
 968                        match request_result {
 969                            ConnectionResult::Timeout => {
 970                                log::warn!("timeout waiting for language server {name} (id {server_id}) to shutdown");
 971                            },
 972                            ConnectionResult::ConnectionReset => {
 973                                log::warn!("language server {name} (id {server_id}) closed the shutdown request connection");
 974                            },
 975                            ConnectionResult::Result(Err(e)) => {
 976                                log::error!("Shutdown request failure, server {name} (id {server_id}): {e:#}");
 977                            },
 978                            ConnectionResult::Result(Ok(())) => {}
 979                        }
 980                    }
 981
 982                    _ = timer => {
 983                        log::info!("timeout waiting for language server {name} (id {server_id}) to shutdown");
 984                    },
 985                }
 986
 987                response_handlers.lock().take();
 988                Self::notify_internal::<notification::Exit>(&notification_serializers, ()).ok();
 989                notification_serializers.close();
 990                output_done.recv().await;
 991                server.lock().take().map(|mut child| child.kill());
 992                drop(tasks);
 993                log::debug!("language server shutdown finished");
 994                Some(())
 995            })
 996        } else {
 997            None
 998        }
 999    }
1000
1001    /// Register a handler to handle incoming LSP notifications.
1002    ///
1003    /// [LSP Specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#notificationMessage)
1004    #[must_use]
1005    pub fn on_notification<T, F>(&self, f: F) -> Subscription
1006    where
1007        T: notification::Notification,
1008        F: 'static + Send + FnMut(T::Params, &mut AsyncApp),
1009    {
1010        self.on_custom_notification(T::METHOD, f)
1011    }
1012
1013    /// Register a handler to handle incoming LSP requests.
1014    ///
1015    /// [LSP Specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#requestMessage)
1016    #[must_use]
1017    pub fn on_request<T, F, Fut>(&self, f: F) -> Subscription
1018    where
1019        T: request::Request,
1020        T::Params: 'static + Send,
1021        F: 'static + FnMut(T::Params, &mut AsyncApp) -> Fut + Send,
1022        Fut: 'static + Future<Output = Result<T::Result>>,
1023    {
1024        self.on_custom_request(T::METHOD, f)
1025    }
1026
1027    /// Registers a handler to inspect all language server process stdio.
1028    #[must_use]
1029    pub fn on_io<F>(&self, f: F) -> Subscription
1030    where
1031        F: 'static + Send + FnMut(IoKind, &str),
1032    {
1033        let id = self.next_id.fetch_add(1, SeqCst);
1034        self.io_handlers.lock().insert(id, Box::new(f));
1035        Subscription::Io {
1036            id,
1037            io_handlers: Some(Arc::downgrade(&self.io_handlers)),
1038        }
1039    }
1040
1041    /// Removes a request handler registers via [`Self::on_request`].
1042    pub fn remove_request_handler<T: request::Request>(&self) {
1043        self.notification_handlers.lock().remove(T::METHOD);
1044    }
1045
1046    /// Removes a notification handler registers via [`Self::on_notification`].
1047    pub fn remove_notification_handler<T: notification::Notification>(&self) {
1048        self.notification_handlers.lock().remove(T::METHOD);
1049    }
1050
1051    /// Checks if a notification handler has been registered via [`Self::on_notification`].
1052    pub fn has_notification_handler<T: notification::Notification>(&self) -> bool {
1053        self.notification_handlers.lock().contains_key(T::METHOD)
1054    }
1055
1056    #[must_use]
1057    fn on_custom_notification<Params, F>(&self, method: &'static str, mut f: F) -> Subscription
1058    where
1059        F: 'static + FnMut(Params, &mut AsyncApp) + Send,
1060        Params: DeserializeOwned,
1061    {
1062        let prev_handler = self.notification_handlers.lock().insert(
1063            method,
1064            Box::new(move |_, params, cx| {
1065                if let Some(params) = serde_json::from_value(params).log_err() {
1066                    f(params, cx);
1067                }
1068            }),
1069        );
1070        assert!(
1071            prev_handler.is_none(),
1072            "registered multiple handlers for the same LSP method"
1073        );
1074        Subscription::Notification {
1075            method,
1076            notification_handlers: Some(self.notification_handlers.clone()),
1077        }
1078    }
1079
1080    #[must_use]
1081    fn on_custom_request<Params, Res, Fut, F>(&self, method: &'static str, mut f: F) -> Subscription
1082    where
1083        F: 'static + FnMut(Params, &mut AsyncApp) -> Fut + Send,
1084        Fut: 'static + Future<Output = Result<Res>>,
1085        Params: DeserializeOwned + Send + 'static,
1086        Res: Serialize,
1087    {
1088        let outbound_tx = self.outbound_tx.clone();
1089        let prev_handler = self.notification_handlers.lock().insert(
1090            method,
1091            Box::new(move |id, params, cx| {
1092                if let Some(id) = id {
1093                    match serde_json::from_value(params) {
1094                        Ok(params) => {
1095                            let response = f(params, cx);
1096                            cx.foreground_executor()
1097                                .spawn({
1098                                    let outbound_tx = outbound_tx.clone();
1099                                    async move {
1100                                        let response = match response.await {
1101                                            Ok(result) => Response {
1102                                                jsonrpc: JSON_RPC_VERSION,
1103                                                id,
1104                                                value: LspResult::Ok(Some(result)),
1105                                            },
1106                                            Err(error) => Response {
1107                                                jsonrpc: JSON_RPC_VERSION,
1108                                                id,
1109                                                value: LspResult::Error(Some(Error {
1110                                                    code: lsp_types::error_codes::REQUEST_FAILED,
1111                                                    message: error.to_string(),
1112                                                    data: None,
1113                                                })),
1114                                            },
1115                                        };
1116                                        if let Some(response) =
1117                                            serde_json::to_string(&response).log_err()
1118                                        {
1119                                            outbound_tx.try_send(response).ok();
1120                                        }
1121                                    }
1122                                })
1123                                .detach();
1124                        }
1125
1126                        Err(error) => {
1127                            log::error!("error deserializing {} request: {:?}", method, error);
1128                            let response = AnyResponse {
1129                                jsonrpc: JSON_RPC_VERSION,
1130                                id,
1131                                result: None,
1132                                error: Some(Error {
1133                                    code: -32700, // Parse error
1134                                    message: error.to_string(),
1135                                    data: None,
1136                                }),
1137                            };
1138                            if let Some(response) = serde_json::to_string(&response).log_err() {
1139                                outbound_tx.try_send(response).ok();
1140                            }
1141                        }
1142                    }
1143                }
1144            }),
1145        );
1146        assert!(
1147            prev_handler.is_none(),
1148            "registered multiple handlers for the same LSP method"
1149        );
1150        Subscription::Notification {
1151            method,
1152            notification_handlers: Some(self.notification_handlers.clone()),
1153        }
1154    }
1155
1156    /// Get the name of the running language server.
1157    pub fn name(&self) -> LanguageServerName {
1158        self.name.clone()
1159    }
1160
1161    /// Get the version of the running language server.
1162    pub fn version(&self) -> Option<SharedString> {
1163        self.version.clone()
1164    }
1165
1166    pub fn process_name(&self) -> &str {
1167        &self.process_name
1168    }
1169
1170    /// Get the reported capabilities of the running language server.
1171    pub fn capabilities(&self) -> ServerCapabilities {
1172        self.capabilities.read().clone()
1173    }
1174
1175    /// Get the reported capabilities of the running language server and
1176    /// what we know on the client/adapter-side of its capabilities.
1177    pub fn adapter_server_capabilities(&self) -> AdapterServerCapabilities {
1178        AdapterServerCapabilities {
1179            server_capabilities: self.capabilities(),
1180            code_action_kinds: self.code_action_kinds(),
1181        }
1182    }
1183
1184    pub fn update_capabilities(&self, update: impl FnOnce(&mut ServerCapabilities)) {
1185        update(self.capabilities.write().deref_mut());
1186    }
1187
1188    pub fn configuration(&self) -> &Value {
1189        &self.configuration.settings
1190    }
1191
1192    /// Get the id of the running language server.
1193    pub fn server_id(&self) -> LanguageServerId {
1194        self.server_id
1195    }
1196
1197    /// Language server's binary information.
1198    pub fn binary(&self) -> &LanguageServerBinary {
1199        &self.binary
1200    }
1201
1202    /// Sends a RPC request to the language server.
1203    ///
1204    /// [LSP Specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#requestMessage)
1205    pub fn request<T: request::Request>(
1206        &self,
1207        params: T::Params,
1208    ) -> impl LspRequestFuture<T::Result> + use<T>
1209    where
1210        T::Result: 'static + Send,
1211    {
1212        Self::request_internal::<T>(
1213            &self.next_id,
1214            &self.response_handlers,
1215            &self.outbound_tx,
1216            &self.notification_tx,
1217            &self.executor,
1218            params,
1219        )
1220    }
1221
1222    /// Sends a RPC request to the language server, with a custom timer, a future which when becoming
1223    /// ready causes the request to be timed out with the future's output message.
1224    ///
1225    /// [LSP Specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#requestMessage)
1226    pub fn request_with_timer<T: request::Request, U: Future<Output = String>>(
1227        &self,
1228        params: T::Params,
1229        timer: U,
1230    ) -> impl LspRequestFuture<T::Result> + use<T, U>
1231    where
1232        T::Result: 'static + Send,
1233    {
1234        Self::request_internal_with_timer::<T, U>(
1235            &self.next_id,
1236            &self.response_handlers,
1237            &self.outbound_tx,
1238            &self.notification_tx,
1239            &self.executor,
1240            timer,
1241            params,
1242        )
1243    }
1244
1245    fn request_internal_with_timer<T, U>(
1246        next_id: &AtomicI32,
1247        response_handlers: &Mutex<Option<HashMap<RequestId, ResponseHandler>>>,
1248        outbound_tx: &channel::Sender<String>,
1249        notification_serializers: &channel::Sender<NotificationSerializer>,
1250        executor: &BackgroundExecutor,
1251        timer: U,
1252        params: T::Params,
1253    ) -> impl LspRequestFuture<T::Result> + use<T, U>
1254    where
1255        T::Result: 'static + Send,
1256        T: request::Request,
1257        U: Future<Output = String>,
1258    {
1259        let id = next_id.fetch_add(1, SeqCst);
1260        let message = serde_json::to_string(&Request {
1261            jsonrpc: JSON_RPC_VERSION,
1262            id: RequestId::Int(id),
1263            method: T::METHOD,
1264            params,
1265        })
1266        .unwrap();
1267
1268        let (tx, rx) = oneshot::channel();
1269        let handle_response = response_handlers
1270            .lock()
1271            .as_mut()
1272            .context("server shut down")
1273            .map(|handlers| {
1274                let executor = executor.clone();
1275                handlers.insert(
1276                    RequestId::Int(id),
1277                    Box::new(move |result| {
1278                        executor
1279                            .spawn(async move {
1280                                let response = match result {
1281                                    Ok(response) => match serde_json::from_str(&response) {
1282                                        Ok(deserialized) => Ok(deserialized),
1283                                        Err(error) => {
1284                                            log::error!("failed to deserialize response from language server: {}. response from language server: {:?}", error, response);
1285                                            Err(error).context("failed to deserialize response")
1286                                        }
1287                                    }
1288                                    Err(error) => Err(anyhow!("{}", error.message)),
1289                                };
1290                                _ = tx.send(response);
1291                            })
1292                            .detach();
1293                    }),
1294                );
1295            });
1296
1297        let send = outbound_tx
1298            .try_send(message)
1299            .context("failed to write to language server's stdin");
1300
1301        let notification_serializers = notification_serializers.downgrade();
1302        let started = Instant::now();
1303        LspRequest::new(id, async move {
1304            if let Err(e) = handle_response {
1305                return ConnectionResult::Result(Err(e));
1306            }
1307            if let Err(e) = send {
1308                return ConnectionResult::Result(Err(e));
1309            }
1310
1311            let cancel_on_drop = util::defer(move || {
1312                if let Some(notification_serializers) = notification_serializers.upgrade() {
1313                    Self::notify_internal::<notification::Cancel>(
1314                        &notification_serializers,
1315                        CancelParams {
1316                            id: NumberOrString::Number(id),
1317                        },
1318                    )
1319                    .ok();
1320                }
1321            });
1322
1323            let method = T::METHOD;
1324            select! {
1325                response = rx.fuse() => {
1326                    let elapsed = started.elapsed();
1327                    log::trace!("Took {elapsed:?} to receive response to {method:?} id {id}");
1328                    cancel_on_drop.abort();
1329                    match response {
1330                        Ok(response_result) => ConnectionResult::Result(response_result),
1331                        Err(Canceled) => {
1332                            log::error!("Server reset connection for a request {method:?} id {id}");
1333                            ConnectionResult::ConnectionReset
1334                        },
1335                    }
1336                }
1337
1338                message = timer.fuse() => {
1339                    log::error!("Cancelled LSP request task for {method:?} id {id} {message}");
1340                    ConnectionResult::Timeout
1341                }
1342            }
1343        })
1344    }
1345
1346    fn request_internal<T>(
1347        next_id: &AtomicI32,
1348        response_handlers: &Mutex<Option<HashMap<RequestId, ResponseHandler>>>,
1349        outbound_tx: &channel::Sender<String>,
1350        notification_serializers: &channel::Sender<NotificationSerializer>,
1351        executor: &BackgroundExecutor,
1352        params: T::Params,
1353    ) -> impl LspRequestFuture<T::Result> + use<T>
1354    where
1355        T::Result: 'static + Send,
1356        T: request::Request,
1357    {
1358        Self::request_internal_with_timer::<T, _>(
1359            next_id,
1360            response_handlers,
1361            outbound_tx,
1362            notification_serializers,
1363            executor,
1364            Self::default_request_timer(executor.clone()),
1365            params,
1366        )
1367    }
1368
1369    pub fn default_request_timer(executor: BackgroundExecutor) -> impl Future<Output = String> {
1370        executor
1371            .timer(LSP_REQUEST_TIMEOUT)
1372            .map(|_| format!("which took over {LSP_REQUEST_TIMEOUT:?}"))
1373    }
1374
1375    /// Sends a RPC notification to the language server.
1376    ///
1377    /// [LSP Specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#notificationMessage)
1378    pub fn notify<T: notification::Notification>(&self, params: T::Params) -> Result<()> {
1379        let outbound = self.notification_tx.clone();
1380        Self::notify_internal::<T>(&outbound, params)
1381    }
1382
1383    fn notify_internal<T: notification::Notification>(
1384        outbound_tx: &channel::Sender<NotificationSerializer>,
1385        params: T::Params,
1386    ) -> Result<()> {
1387        let serializer = NotificationSerializer(Box::new(move || {
1388            serde_json::to_string(&Notification {
1389                jsonrpc: JSON_RPC_VERSION,
1390                method: T::METHOD,
1391                params,
1392            })
1393            .unwrap()
1394        }));
1395
1396        outbound_tx.send_blocking(serializer)?;
1397        Ok(())
1398    }
1399
1400    /// Add new workspace folder to the list.
1401    pub fn add_workspace_folder(&self, uri: Uri) {
1402        if self
1403            .capabilities()
1404            .workspace
1405            .and_then(|ws| {
1406                ws.workspace_folders.and_then(|folders| {
1407                    folders
1408                        .change_notifications
1409                        .map(|caps| matches!(caps, OneOf::Left(false)))
1410                })
1411            })
1412            .unwrap_or(true)
1413        {
1414            return;
1415        }
1416
1417        let Some(workspace_folders) = self.workspace_folders.as_ref() else {
1418            return;
1419        };
1420        let is_new_folder = workspace_folders.lock().insert(uri.clone());
1421        if is_new_folder {
1422            let params = DidChangeWorkspaceFoldersParams {
1423                event: WorkspaceFoldersChangeEvent {
1424                    added: vec![WorkspaceFolder {
1425                        uri,
1426                        name: String::default(),
1427                    }],
1428                    removed: vec![],
1429                },
1430            };
1431            self.notify::<DidChangeWorkspaceFolders>(params).ok();
1432        }
1433    }
1434
1435    /// Remove existing workspace folder from the list.
1436    pub fn remove_workspace_folder(&self, uri: Uri) {
1437        if self
1438            .capabilities()
1439            .workspace
1440            .and_then(|ws| {
1441                ws.workspace_folders.and_then(|folders| {
1442                    folders
1443                        .change_notifications
1444                        .map(|caps| !matches!(caps, OneOf::Left(false)))
1445                })
1446            })
1447            .unwrap_or(true)
1448        {
1449            return;
1450        }
1451        let Some(workspace_folders) = self.workspace_folders.as_ref() else {
1452            return;
1453        };
1454        let was_removed = workspace_folders.lock().remove(&uri);
1455        if was_removed {
1456            let params = DidChangeWorkspaceFoldersParams {
1457                event: WorkspaceFoldersChangeEvent {
1458                    added: vec![],
1459                    removed: vec![WorkspaceFolder {
1460                        uri,
1461                        name: String::default(),
1462                    }],
1463                },
1464            };
1465            self.notify::<DidChangeWorkspaceFolders>(params).ok();
1466        }
1467    }
1468    pub fn set_workspace_folders(&self, folders: BTreeSet<Uri>) {
1469        let Some(workspace_folders) = self.workspace_folders.as_ref() else {
1470            return;
1471        };
1472        let mut workspace_folders = workspace_folders.lock();
1473
1474        let old_workspace_folders = std::mem::take(&mut *workspace_folders);
1475        let added: Vec<_> = folders
1476            .difference(&old_workspace_folders)
1477            .map(|uri| WorkspaceFolder {
1478                uri: uri.clone(),
1479                name: String::default(),
1480            })
1481            .collect();
1482
1483        let removed: Vec<_> = old_workspace_folders
1484            .difference(&folders)
1485            .map(|uri| WorkspaceFolder {
1486                uri: uri.clone(),
1487                name: String::default(),
1488            })
1489            .collect();
1490        *workspace_folders = folders;
1491        let should_notify = !added.is_empty() || !removed.is_empty();
1492        if should_notify {
1493            drop(workspace_folders);
1494            let params = DidChangeWorkspaceFoldersParams {
1495                event: WorkspaceFoldersChangeEvent { added, removed },
1496            };
1497            self.notify::<DidChangeWorkspaceFolders>(params).ok();
1498        }
1499    }
1500
1501    pub fn workspace_folders(&self) -> BTreeSet<Uri> {
1502        self.workspace_folders.as_ref().map_or_else(
1503            || BTreeSet::from_iter([self.root_uri.clone()]),
1504            |folders| folders.lock().clone(),
1505        )
1506    }
1507
1508    pub fn register_buffer(
1509        &self,
1510        uri: Uri,
1511        language_id: String,
1512        version: i32,
1513        initial_text: String,
1514    ) {
1515        self.notify::<notification::DidOpenTextDocument>(DidOpenTextDocumentParams {
1516            text_document: TextDocumentItem::new(uri, language_id, version, initial_text),
1517        })
1518        .ok();
1519    }
1520
1521    pub fn unregister_buffer(&self, uri: Uri) {
1522        self.notify::<notification::DidCloseTextDocument>(DidCloseTextDocumentParams {
1523            text_document: TextDocumentIdentifier::new(uri),
1524        })
1525        .ok();
1526    }
1527}
1528
1529impl Drop for LanguageServer {
1530    fn drop(&mut self) {
1531        if let Some(shutdown) = self.shutdown() {
1532            self.executor.spawn(shutdown).detach();
1533        }
1534    }
1535}
1536
1537impl Subscription {
1538    /// Detaching a subscription handle prevents it from unsubscribing on drop.
1539    pub fn detach(&mut self) {
1540        match self {
1541            Subscription::Notification {
1542                notification_handlers,
1543                ..
1544            } => *notification_handlers = None,
1545            Subscription::Io { io_handlers, .. } => *io_handlers = None,
1546        }
1547    }
1548}
1549
1550impl fmt::Display for LanguageServerId {
1551    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1552        self.0.fmt(f)
1553    }
1554}
1555
1556impl fmt::Debug for LanguageServer {
1557    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1558        f.debug_struct("LanguageServer")
1559            .field("id", &self.server_id.0)
1560            .field("name", &self.name)
1561            .finish_non_exhaustive()
1562    }
1563}
1564
1565impl fmt::Debug for LanguageServerBinary {
1566    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1567        let mut debug = f.debug_struct("LanguageServerBinary");
1568        debug.field("path", &self.path);
1569        debug.field("arguments", &self.arguments);
1570
1571        if let Some(env) = &self.env {
1572            let redacted_env: BTreeMap<String, String> = env
1573                .iter()
1574                .map(|(key, value)| {
1575                    let redacted_value = if redact::should_redact(key) {
1576                        "REDACTED".to_string()
1577                    } else {
1578                        value.clone()
1579                    };
1580                    (key.clone(), redacted_value)
1581                })
1582                .collect();
1583            debug.field("env", &Some(redacted_env));
1584        } else {
1585            debug.field("env", &self.env);
1586        }
1587
1588        debug.finish()
1589    }
1590}
1591
1592impl Drop for Subscription {
1593    fn drop(&mut self) {
1594        match self {
1595            Subscription::Notification {
1596                method,
1597                notification_handlers,
1598            } => {
1599                if let Some(handlers) = notification_handlers {
1600                    handlers.lock().remove(method);
1601                }
1602            }
1603            Subscription::Io { id, io_handlers } => {
1604                if let Some(io_handlers) = io_handlers.as_ref().and_then(|h| h.upgrade()) {
1605                    io_handlers.lock().remove(id);
1606                }
1607            }
1608        }
1609    }
1610}
1611
1612/// Mock language server for use in tests.
1613#[cfg(any(test, feature = "test-support"))]
1614#[derive(Clone)]
1615pub struct FakeLanguageServer {
1616    pub binary: LanguageServerBinary,
1617    pub server: Arc<LanguageServer>,
1618    notifications_rx: channel::Receiver<(String, String)>,
1619}
1620
1621#[cfg(any(test, feature = "test-support"))]
1622impl FakeLanguageServer {
1623    /// Construct a fake language server.
1624    pub fn new(
1625        server_id: LanguageServerId,
1626        binary: LanguageServerBinary,
1627        name: String,
1628        capabilities: ServerCapabilities,
1629        cx: &mut AsyncApp,
1630    ) -> (LanguageServer, FakeLanguageServer) {
1631        let (stdin_writer, stdin_reader) = async_pipe::pipe();
1632        let (stdout_writer, stdout_reader) = async_pipe::pipe();
1633        let (notifications_tx, notifications_rx) = channel::unbounded();
1634
1635        let server_name = LanguageServerName(name.clone().into());
1636        let process_name = Arc::from(name.as_str());
1637        let root = Self::root_path();
1638        let workspace_folders: Arc<Mutex<BTreeSet<Uri>>> = Default::default();
1639        let mut server = LanguageServer::new_internal(
1640            server_id,
1641            server_name.clone(),
1642            stdin_writer,
1643            stdout_reader,
1644            None::<async_pipe::PipeReader>,
1645            Arc::new(Mutex::new(None)),
1646            None,
1647            None,
1648            binary.clone(),
1649            root,
1650            Some(workspace_folders.clone()),
1651            cx,
1652            |_| false,
1653        );
1654        server.process_name = process_name;
1655        let fake = FakeLanguageServer {
1656            binary: binary.clone(),
1657            server: Arc::new({
1658                let mut server = LanguageServer::new_internal(
1659                    server_id,
1660                    server_name,
1661                    stdout_writer,
1662                    stdin_reader,
1663                    None::<async_pipe::PipeReader>,
1664                    Arc::new(Mutex::new(None)),
1665                    None,
1666                    None,
1667                    binary,
1668                    Self::root_path(),
1669                    Some(workspace_folders),
1670                    cx,
1671                    move |msg| {
1672                        notifications_tx
1673                            .try_send((
1674                                msg.method.to_string(),
1675                                msg.params.as_ref().unwrap_or(&Value::Null).to_string(),
1676                            ))
1677                            .ok();
1678                        true
1679                    },
1680                );
1681                server.process_name = name.as_str().into();
1682                server
1683            }),
1684            notifications_rx,
1685        };
1686        fake.set_request_handler::<request::Initialize, _, _>({
1687            let capabilities = capabilities;
1688            move |_, _| {
1689                let capabilities = capabilities.clone();
1690                let name = name.clone();
1691                async move {
1692                    Ok(InitializeResult {
1693                        capabilities,
1694                        server_info: Some(ServerInfo {
1695                            name,
1696                            ..Default::default()
1697                        }),
1698                    })
1699                }
1700            }
1701        });
1702
1703        fake.set_request_handler::<request::Shutdown, _, _>(|_, _| async move { Ok(()) });
1704
1705        (server, fake)
1706    }
1707    #[cfg(target_os = "windows")]
1708    fn root_path() -> Uri {
1709        Uri::from_file_path("C:/").unwrap()
1710    }
1711
1712    #[cfg(not(target_os = "windows"))]
1713    fn root_path() -> Uri {
1714        Uri::from_file_path("/").unwrap()
1715    }
1716}
1717
1718#[cfg(any(test, feature = "test-support"))]
1719impl LanguageServer {
1720    pub fn full_capabilities() -> ServerCapabilities {
1721        ServerCapabilities {
1722            document_highlight_provider: Some(OneOf::Left(true)),
1723            code_action_provider: Some(CodeActionProviderCapability::Simple(true)),
1724            document_formatting_provider: Some(OneOf::Left(true)),
1725            document_range_formatting_provider: Some(OneOf::Left(true)),
1726            definition_provider: Some(OneOf::Left(true)),
1727            workspace_symbol_provider: Some(OneOf::Left(true)),
1728            implementation_provider: Some(ImplementationProviderCapability::Simple(true)),
1729            type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)),
1730            ..ServerCapabilities::default()
1731        }
1732    }
1733}
1734
1735#[cfg(any(test, feature = "test-support"))]
1736impl FakeLanguageServer {
1737    /// See [`LanguageServer::notify`].
1738    pub fn notify<T: notification::Notification>(&self, params: T::Params) {
1739        self.server.notify::<T>(params).ok();
1740    }
1741
1742    /// See [`LanguageServer::request`].
1743    pub async fn request<T>(&self, params: T::Params) -> ConnectionResult<T::Result>
1744    where
1745        T: request::Request,
1746        T::Result: 'static + Send,
1747    {
1748        self.server.executor.start_waiting();
1749        self.server.request::<T>(params).await
1750    }
1751
1752    /// Attempts [`Self::try_receive_notification`], unwrapping if it has not received the specified type yet.
1753    pub async fn receive_notification<T: notification::Notification>(&mut self) -> T::Params {
1754        self.server.executor.start_waiting();
1755        self.try_receive_notification::<T>().await.unwrap()
1756    }
1757
1758    /// Consumes the notification channel until it finds a notification for the specified type.
1759    pub async fn try_receive_notification<T: notification::Notification>(
1760        &mut self,
1761    ) -> Option<T::Params> {
1762        loop {
1763            let (method, params) = self.notifications_rx.recv().await.ok()?;
1764            if method == T::METHOD {
1765                return Some(serde_json::from_str::<T::Params>(&params).unwrap());
1766            } else {
1767                log::info!("skipping message in fake language server {:?}", params);
1768            }
1769        }
1770    }
1771
1772    /// Registers a handler for a specific kind of request. Removes any existing handler for specified request type.
1773    pub fn set_request_handler<T, F, Fut>(
1774        &self,
1775        mut handler: F,
1776    ) -> futures::channel::mpsc::UnboundedReceiver<()>
1777    where
1778        T: 'static + request::Request,
1779        T::Params: 'static + Send,
1780        F: 'static + Send + FnMut(T::Params, gpui::AsyncApp) -> Fut,
1781        Fut: 'static + Future<Output = Result<T::Result>>,
1782    {
1783        let (responded_tx, responded_rx) = futures::channel::mpsc::unbounded();
1784        self.server.remove_request_handler::<T>();
1785        self.server
1786            .on_request::<T, _, _>(move |params, cx| {
1787                let result = handler(params, cx.clone());
1788                let responded_tx = responded_tx.clone();
1789                let executor = cx.background_executor().clone();
1790                async move {
1791                    executor.simulate_random_delay().await;
1792                    let result = result.await;
1793                    responded_tx.unbounded_send(()).ok();
1794                    result
1795                }
1796            })
1797            .detach();
1798        responded_rx
1799    }
1800
1801    /// Registers a handler for a specific kind of notification. Removes any existing handler for specified notification type.
1802    pub fn handle_notification<T, F>(
1803        &self,
1804        mut handler: F,
1805    ) -> futures::channel::mpsc::UnboundedReceiver<()>
1806    where
1807        T: 'static + notification::Notification,
1808        T::Params: 'static + Send,
1809        F: 'static + Send + FnMut(T::Params, gpui::AsyncApp),
1810    {
1811        let (handled_tx, handled_rx) = futures::channel::mpsc::unbounded();
1812        self.server.remove_notification_handler::<T>();
1813        self.server
1814            .on_notification::<T, _>(move |params, cx| {
1815                handler(params, cx.clone());
1816                handled_tx.unbounded_send(()).ok();
1817            })
1818            .detach();
1819        handled_rx
1820    }
1821
1822    /// Removes any existing handler for specified notification type.
1823    pub fn remove_request_handler<T>(&mut self)
1824    where
1825        T: 'static + request::Request,
1826    {
1827        self.server.remove_request_handler::<T>();
1828    }
1829
1830    /// Simulate that the server has started work and notifies about its progress with the specified token.
1831    pub async fn start_progress(&self, token: impl Into<String>) {
1832        self.start_progress_with(token, Default::default()).await
1833    }
1834
1835    pub async fn start_progress_with(
1836        &self,
1837        token: impl Into<String>,
1838        progress: WorkDoneProgressBegin,
1839    ) {
1840        let token = token.into();
1841        self.request::<request::WorkDoneProgressCreate>(WorkDoneProgressCreateParams {
1842            token: NumberOrString::String(token.clone()),
1843        })
1844        .await
1845        .into_response()
1846        .unwrap();
1847        self.notify::<notification::Progress>(ProgressParams {
1848            token: NumberOrString::String(token),
1849            value: ProgressParamsValue::WorkDone(WorkDoneProgress::Begin(progress)),
1850        });
1851    }
1852
1853    /// Simulate that the server has completed work and notifies about that with the specified token.
1854    pub fn end_progress(&self, token: impl Into<String>) {
1855        self.notify::<notification::Progress>(ProgressParams {
1856            token: NumberOrString::String(token.into()),
1857            value: ProgressParamsValue::WorkDone(WorkDoneProgress::End(Default::default())),
1858        });
1859    }
1860}
1861
1862#[cfg(test)]
1863mod tests {
1864    use super::*;
1865    use gpui::TestAppContext;
1866    use std::str::FromStr;
1867
1868    #[ctor::ctor]
1869    fn init_logger() {
1870        zlog::init_test();
1871    }
1872
1873    #[gpui::test]
1874    async fn test_fake(cx: &mut TestAppContext) {
1875        cx.update(|cx| {
1876            release_channel::init(semver::Version::new(0, 0, 0), cx);
1877        });
1878        let (server, mut fake) = FakeLanguageServer::new(
1879            LanguageServerId(0),
1880            LanguageServerBinary {
1881                path: "path/to/language-server".into(),
1882                arguments: vec![],
1883                env: None,
1884            },
1885            "the-lsp".to_string(),
1886            Default::default(),
1887            &mut cx.to_async(),
1888        );
1889
1890        let (message_tx, message_rx) = channel::unbounded();
1891        let (diagnostics_tx, diagnostics_rx) = channel::unbounded();
1892        server
1893            .on_notification::<notification::ShowMessage, _>(move |params, _| {
1894                message_tx.try_send(params).unwrap()
1895            })
1896            .detach();
1897        server
1898            .on_notification::<notification::PublishDiagnostics, _>(move |params, _| {
1899                diagnostics_tx.try_send(params).unwrap()
1900            })
1901            .detach();
1902
1903        let server = cx
1904            .update(|cx| {
1905                let params = server.default_initialize_params(false, cx);
1906                let configuration = DidChangeConfigurationParams {
1907                    settings: Default::default(),
1908                };
1909                server.initialize(params, configuration.into(), cx)
1910            })
1911            .await
1912            .unwrap();
1913        server
1914            .notify::<notification::DidOpenTextDocument>(DidOpenTextDocumentParams {
1915                text_document: TextDocumentItem::new(
1916                    Uri::from_str("file://a/b").unwrap(),
1917                    "rust".to_string(),
1918                    0,
1919                    "".to_string(),
1920                ),
1921            })
1922            .unwrap();
1923        assert_eq!(
1924            fake.receive_notification::<notification::DidOpenTextDocument>()
1925                .await
1926                .text_document
1927                .uri
1928                .as_str(),
1929            "file://a/b"
1930        );
1931
1932        fake.notify::<notification::ShowMessage>(ShowMessageParams {
1933            typ: MessageType::ERROR,
1934            message: "ok".to_string(),
1935        });
1936        fake.notify::<notification::PublishDiagnostics>(PublishDiagnosticsParams {
1937            uri: Uri::from_str("file://b/c").unwrap(),
1938            version: Some(5),
1939            diagnostics: vec![],
1940        });
1941        assert_eq!(message_rx.recv().await.unwrap().message, "ok");
1942        assert_eq!(
1943            diagnostics_rx.recv().await.unwrap().uri.as_str(),
1944            "file://b/c"
1945        );
1946
1947        fake.set_request_handler::<request::Shutdown, _, _>(|_, _| async move { Ok(()) });
1948
1949        drop(server);
1950        cx.run_until_parked();
1951        fake.receive_notification::<notification::Exit>().await;
1952    }
1953
1954    #[gpui::test]
1955    fn test_deserialize_string_digit_id() {
1956        let json = r#"{"jsonrpc":"2.0","id":"2","method":"workspace/configuration","params":{"items":[{"scopeUri":"file:///Users/mph/Devel/personal/hello-scala/","section":"metals"}]}}"#;
1957        let notification = serde_json::from_str::<NotificationOrRequest>(json)
1958            .expect("message with string id should be parsed");
1959        let expected_id = RequestId::Str("2".to_string());
1960        assert_eq!(notification.id, Some(expected_id));
1961    }
1962
1963    #[gpui::test]
1964    fn test_deserialize_string_id() {
1965        let json = r#"{"jsonrpc":"2.0","id":"anythingAtAll","method":"workspace/configuration","params":{"items":[{"scopeUri":"file:///Users/mph/Devel/personal/hello-scala/","section":"metals"}]}}"#;
1966        let notification = serde_json::from_str::<NotificationOrRequest>(json)
1967            .expect("message with string id should be parsed");
1968        let expected_id = RequestId::Str("anythingAtAll".to_string());
1969        assert_eq!(notification.id, Some(expected_id));
1970    }
1971
1972    #[gpui::test]
1973    fn test_deserialize_int_id() {
1974        let json = r#"{"jsonrpc":"2.0","id":2,"method":"workspace/configuration","params":{"items":[{"scopeUri":"file:///Users/mph/Devel/personal/hello-scala/","section":"metals"}]}}"#;
1975        let notification = serde_json::from_str::<NotificationOrRequest>(json)
1976            .expect("message with string id should be parsed");
1977        let expected_id = RequestId::Int(2);
1978        assert_eq!(notification.id, Some(expected_id));
1979    }
1980
1981    #[test]
1982    fn test_serialize_has_no_nulls() {
1983        // Ensure we're not setting both result and error variants. (ticket #10595)
1984        let no_tag = Response::<u32> {
1985            jsonrpc: "",
1986            id: RequestId::Int(0),
1987            value: LspResult::Ok(None),
1988        };
1989        assert_eq!(
1990            serde_json::to_string(&no_tag).unwrap(),
1991            "{\"jsonrpc\":\"\",\"id\":0,\"result\":null}"
1992        );
1993        let no_tag = Response::<u32> {
1994            jsonrpc: "",
1995            id: RequestId::Int(0),
1996            value: LspResult::Error(None),
1997        };
1998        assert_eq!(
1999            serde_json::to_string(&no_tag).unwrap(),
2000            "{\"jsonrpc\":\"\",\"id\":0,\"error\":null}"
2001        );
2002    }
2003}