lsp.rs

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