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    /// Get effective capabilities by combining static and dynamic capabilities.
1152    pub fn effective_capability<Cap: EffectiveCapability>(&self) -> Cap::Value {
1153        let static_capabilities = self.capabilities();
1154        let dynamic_capabilities = self.dynamic_capabilities.read().clone();
1155        Cap::compute(&static_capabilities, &dynamic_capabilities)
1156    }
1157
1158    /// Get the reported capabilities of the running language server and
1159    /// what we know on the client/adapter-side of its capabilities.
1160    pub fn adapter_server_capabilities(&self) -> AdapterServerCapabilities {
1161        AdapterServerCapabilities {
1162            server_capabilities: self.capabilities(),
1163            code_action_kinds: self.code_action_kinds(),
1164        }
1165    }
1166
1167    pub fn update_capabilities(&self, update: impl FnOnce(&mut ServerCapabilities)) {
1168        update(self.static_capabilities.write().deref_mut());
1169    }
1170
1171    pub fn configuration(&self) -> &Value {
1172        &self.configuration.settings
1173    }
1174
1175    /// Get the id of the running language server.
1176    pub fn server_id(&self) -> LanguageServerId {
1177        self.server_id
1178    }
1179
1180    /// Language server's binary information.
1181    pub fn binary(&self) -> &LanguageServerBinary {
1182        &self.binary
1183    }
1184
1185    /// Sends a RPC request to the language server.
1186    ///
1187    /// [LSP Specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#requestMessage)
1188    pub fn request<T: request::Request>(
1189        &self,
1190        params: T::Params,
1191    ) -> impl LspRequestFuture<T::Result> + use<T>
1192    where
1193        T::Result: 'static + Send,
1194    {
1195        Self::request_internal::<T>(
1196            &self.next_id,
1197            &self.response_handlers,
1198            &self.outbound_tx,
1199            &self.executor,
1200            params,
1201        )
1202    }
1203
1204    /// Sends a RPC request to the language server, with a custom timer, a future which when becoming
1205    /// ready causes the request to be timed out with the future's output message.
1206    ///
1207    /// [LSP Specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#requestMessage)
1208    pub fn request_with_timer<T: request::Request, U: Future<Output = String>>(
1209        &self,
1210        params: T::Params,
1211        timer: U,
1212    ) -> impl LspRequestFuture<T::Result> + use<T, U>
1213    where
1214        T::Result: 'static + Send,
1215    {
1216        Self::request_internal_with_timer::<T, U>(
1217            &self.next_id,
1218            &self.response_handlers,
1219            &self.outbound_tx,
1220            &self.executor,
1221            timer,
1222            params,
1223        )
1224    }
1225
1226    fn request_internal_with_timer<T, U>(
1227        next_id: &AtomicI32,
1228        response_handlers: &Mutex<Option<HashMap<RequestId, ResponseHandler>>>,
1229        outbound_tx: &channel::Sender<String>,
1230        executor: &BackgroundExecutor,
1231        timer: U,
1232        params: T::Params,
1233    ) -> impl LspRequestFuture<T::Result> + use<T, U>
1234    where
1235        T::Result: 'static + Send,
1236        T: request::Request,
1237        U: Future<Output = String>,
1238    {
1239        let id = next_id.fetch_add(1, SeqCst);
1240        let message = serde_json::to_string(&Request {
1241            jsonrpc: JSON_RPC_VERSION,
1242            id: RequestId::Int(id),
1243            method: T::METHOD,
1244            params,
1245        })
1246        .unwrap();
1247
1248        let (tx, rx) = oneshot::channel();
1249        let handle_response = response_handlers
1250            .lock()
1251            .as_mut()
1252            .context("server shut down")
1253            .map(|handlers| {
1254                let executor = executor.clone();
1255                handlers.insert(
1256                    RequestId::Int(id),
1257                    Box::new(move |result| {
1258                        executor
1259                            .spawn(async move {
1260                                let response = match result {
1261                                    Ok(response) => match serde_json::from_str(&response) {
1262                                        Ok(deserialized) => Ok(deserialized),
1263                                        Err(error) => {
1264                                            log::error!("failed to deserialize response from language server: {}. response from language server: {:?}", error, response);
1265                                            Err(error).context("failed to deserialize response")
1266                                        }
1267                                    }
1268                                    Err(error) => Err(anyhow!("{}", error.message)),
1269                                };
1270                                _ = tx.send(response);
1271                            })
1272                            .detach();
1273                    }),
1274                );
1275            });
1276
1277        let send = outbound_tx
1278            .try_send(message)
1279            .context("failed to write to language server's stdin");
1280
1281        let outbound_tx = outbound_tx.downgrade();
1282        let started = Instant::now();
1283        LspRequest::new(id, async move {
1284            if let Err(e) = handle_response {
1285                return ConnectionResult::Result(Err(e));
1286            }
1287            if let Err(e) = send {
1288                return ConnectionResult::Result(Err(e));
1289            }
1290
1291            let cancel_on_drop = util::defer(move || {
1292                if let Some(outbound_tx) = outbound_tx.upgrade() {
1293                    Self::notify_internal::<notification::Cancel>(
1294                        &outbound_tx,
1295                        &CancelParams {
1296                            id: NumberOrString::Number(id),
1297                        },
1298                    )
1299                    .ok();
1300                }
1301            });
1302
1303            let method = T::METHOD;
1304            select! {
1305                response = rx.fuse() => {
1306                    let elapsed = started.elapsed();
1307                    log::trace!("Took {elapsed:?} to receive response to {method:?} id {id}");
1308                    cancel_on_drop.abort();
1309                    match response {
1310                        Ok(response_result) => ConnectionResult::Result(response_result),
1311                        Err(Canceled) => {
1312                            log::error!("Server reset connection for a request {method:?} id {id}");
1313                            ConnectionResult::ConnectionReset
1314                        },
1315                    }
1316                }
1317
1318                message = timer.fuse() => {
1319                    log::error!("Cancelled LSP request task for {method:?} id {id} {message}");
1320                    ConnectionResult::Timeout
1321                }
1322            }
1323        })
1324    }
1325
1326    fn request_internal<T>(
1327        next_id: &AtomicI32,
1328        response_handlers: &Mutex<Option<HashMap<RequestId, ResponseHandler>>>,
1329        outbound_tx: &channel::Sender<String>,
1330        executor: &BackgroundExecutor,
1331        params: T::Params,
1332    ) -> impl LspRequestFuture<T::Result> + use<T>
1333    where
1334        T::Result: 'static + Send,
1335        T: request::Request,
1336    {
1337        Self::request_internal_with_timer::<T, _>(
1338            next_id,
1339            response_handlers,
1340            outbound_tx,
1341            executor,
1342            Self::default_request_timer(executor.clone()),
1343            params,
1344        )
1345    }
1346
1347    pub fn default_request_timer(executor: BackgroundExecutor) -> impl Future<Output = String> {
1348        executor
1349            .timer(LSP_REQUEST_TIMEOUT)
1350            .map(|_| format!("which took over {LSP_REQUEST_TIMEOUT:?}"))
1351    }
1352
1353    /// Sends a RPC notification to the language server.
1354    ///
1355    /// [LSP Specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#notificationMessage)
1356    pub fn notify<T: notification::Notification>(&self, params: &T::Params) -> Result<()> {
1357        Self::notify_internal::<T>(&self.outbound_tx, params)
1358    }
1359
1360    fn notify_internal<T: notification::Notification>(
1361        outbound_tx: &channel::Sender<String>,
1362        params: &T::Params,
1363    ) -> Result<()> {
1364        let message = serde_json::to_string(&Notification {
1365            jsonrpc: JSON_RPC_VERSION,
1366            method: T::METHOD,
1367            params,
1368        })
1369        .unwrap();
1370        outbound_tx.try_send(message)?;
1371        Ok(())
1372    }
1373
1374    /// Add new workspace folder to the list.
1375    pub fn add_workspace_folder(&self, uri: Url) {
1376        if self
1377            .capabilities()
1378            .workspace
1379            .and_then(|ws| {
1380                ws.workspace_folders.and_then(|folders| {
1381                    folders
1382                        .change_notifications
1383                        .map(|caps| matches!(caps, OneOf::Left(false)))
1384                })
1385            })
1386            .unwrap_or(true)
1387        {
1388            return;
1389        }
1390
1391        let Some(workspace_folders) = self.workspace_folders.as_ref() else {
1392            return;
1393        };
1394        let is_new_folder = workspace_folders.lock().insert(uri.clone());
1395        if is_new_folder {
1396            let params = DidChangeWorkspaceFoldersParams {
1397                event: WorkspaceFoldersChangeEvent {
1398                    added: vec![WorkspaceFolder {
1399                        uri,
1400                        name: String::default(),
1401                    }],
1402                    removed: vec![],
1403                },
1404            };
1405            self.notify::<DidChangeWorkspaceFolders>(&params).ok();
1406        }
1407    }
1408    /// Add new workspace folder to the list.
1409    pub fn remove_workspace_folder(&self, uri: Url) {
1410        if self
1411            .capabilities()
1412            .workspace
1413            .and_then(|ws| {
1414                ws.workspace_folders.and_then(|folders| {
1415                    folders
1416                        .change_notifications
1417                        .map(|caps| !matches!(caps, OneOf::Left(false)))
1418                })
1419            })
1420            .unwrap_or(true)
1421        {
1422            return;
1423        }
1424        let Some(workspace_folders) = self.workspace_folders.as_ref() else {
1425            return;
1426        };
1427        let was_removed = workspace_folders.lock().remove(&uri);
1428        if was_removed {
1429            let params = DidChangeWorkspaceFoldersParams {
1430                event: WorkspaceFoldersChangeEvent {
1431                    added: vec![],
1432                    removed: vec![WorkspaceFolder {
1433                        uri,
1434                        name: String::default(),
1435                    }],
1436                },
1437            };
1438            self.notify::<DidChangeWorkspaceFolders>(&params).ok();
1439        }
1440    }
1441    pub fn set_workspace_folders(&self, folders: BTreeSet<Url>) {
1442        let Some(workspace_folders) = self.workspace_folders.as_ref() else {
1443            return;
1444        };
1445        let mut workspace_folders = workspace_folders.lock();
1446
1447        let old_workspace_folders = std::mem::take(&mut *workspace_folders);
1448        let added: Vec<_> = folders
1449            .difference(&old_workspace_folders)
1450            .map(|uri| WorkspaceFolder {
1451                uri: uri.clone(),
1452                name: String::default(),
1453            })
1454            .collect();
1455
1456        let removed: Vec<_> = old_workspace_folders
1457            .difference(&folders)
1458            .map(|uri| WorkspaceFolder {
1459                uri: uri.clone(),
1460                name: String::default(),
1461            })
1462            .collect();
1463        *workspace_folders = folders;
1464        let should_notify = !added.is_empty() || !removed.is_empty();
1465        if should_notify {
1466            drop(workspace_folders);
1467            let params = DidChangeWorkspaceFoldersParams {
1468                event: WorkspaceFoldersChangeEvent { added, removed },
1469            };
1470            self.notify::<DidChangeWorkspaceFolders>(&params).ok();
1471        }
1472    }
1473
1474    pub fn workspace_folders(&self) -> BTreeSet<Url> {
1475        self.workspace_folders.as_ref().map_or_else(
1476            || BTreeSet::from_iter([self.root_uri.clone()]),
1477            |folders| folders.lock().clone(),
1478        )
1479    }
1480
1481    pub fn register_buffer(
1482        &self,
1483        uri: Url,
1484        language_id: String,
1485        version: i32,
1486        initial_text: String,
1487    ) {
1488        self.notify::<notification::DidOpenTextDocument>(&DidOpenTextDocumentParams {
1489            text_document: TextDocumentItem::new(uri, language_id, version, initial_text),
1490        })
1491        .ok();
1492    }
1493
1494    pub fn unregister_buffer(&self, uri: Url) {
1495        self.notify::<notification::DidCloseTextDocument>(&DidCloseTextDocumentParams {
1496            text_document: TextDocumentIdentifier::new(uri),
1497        })
1498        .ok();
1499    }
1500}
1501
1502impl Drop for LanguageServer {
1503    fn drop(&mut self) {
1504        if let Some(shutdown) = self.shutdown() {
1505            self.executor.spawn(shutdown).detach();
1506        }
1507    }
1508}
1509
1510impl Subscription {
1511    /// Detaching a subscription handle prevents it from unsubscribing on drop.
1512    pub fn detach(&mut self) {
1513        match self {
1514            Subscription::Notification {
1515                notification_handlers,
1516                ..
1517            } => *notification_handlers = None,
1518            Subscription::Io { io_handlers, .. } => *io_handlers = None,
1519        }
1520    }
1521}
1522
1523impl fmt::Display for LanguageServerId {
1524    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1525        self.0.fmt(f)
1526    }
1527}
1528
1529impl fmt::Debug for LanguageServer {
1530    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1531        f.debug_struct("LanguageServer")
1532            .field("id", &self.server_id.0)
1533            .field("name", &self.name)
1534            .finish_non_exhaustive()
1535    }
1536}
1537
1538impl fmt::Debug for LanguageServerBinary {
1539    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1540        let mut debug = f.debug_struct("LanguageServerBinary");
1541        debug.field("path", &self.path);
1542        debug.field("arguments", &self.arguments);
1543
1544        if let Some(env) = &self.env {
1545            let redacted_env: BTreeMap<String, String> = env
1546                .iter()
1547                .map(|(key, value)| {
1548                    let redacted_value = if redact::should_redact(key) {
1549                        "REDACTED".to_string()
1550                    } else {
1551                        value.clone()
1552                    };
1553                    (key.clone(), redacted_value)
1554                })
1555                .collect();
1556            debug.field("env", &Some(redacted_env));
1557        } else {
1558            debug.field("env", &self.env);
1559        }
1560
1561        debug.finish()
1562    }
1563}
1564
1565impl Drop for Subscription {
1566    fn drop(&mut self) {
1567        match self {
1568            Subscription::Notification {
1569                method,
1570                notification_handlers,
1571            } => {
1572                if let Some(handlers) = notification_handlers {
1573                    handlers.lock().remove(method);
1574                }
1575            }
1576            Subscription::Io { id, io_handlers } => {
1577                if let Some(io_handlers) = io_handlers.as_ref().and_then(|h| h.upgrade()) {
1578                    io_handlers.lock().remove(id);
1579                }
1580            }
1581        }
1582    }
1583}
1584
1585/// Mock language server for use in tests.
1586#[cfg(any(test, feature = "test-support"))]
1587#[derive(Clone)]
1588pub struct FakeLanguageServer {
1589    pub binary: LanguageServerBinary,
1590    pub server: Arc<LanguageServer>,
1591    notifications_rx: channel::Receiver<(String, String)>,
1592}
1593
1594#[cfg(any(test, feature = "test-support"))]
1595impl FakeLanguageServer {
1596    /// Construct a fake language server.
1597    pub fn new(
1598        server_id: LanguageServerId,
1599        binary: LanguageServerBinary,
1600        name: String,
1601        capabilities: ServerCapabilities,
1602        cx: &mut AsyncApp,
1603    ) -> (LanguageServer, FakeLanguageServer) {
1604        let (stdin_writer, stdin_reader) = async_pipe::pipe();
1605        let (stdout_writer, stdout_reader) = async_pipe::pipe();
1606        let (notifications_tx, notifications_rx) = channel::unbounded();
1607
1608        let server_name = LanguageServerName(name.clone().into());
1609        let process_name = Arc::from(name.as_str());
1610        let root = Self::root_path();
1611        let workspace_folders: Arc<Mutex<BTreeSet<Url>>> = Default::default();
1612        let mut server = LanguageServer::new_internal(
1613            server_id,
1614            server_name.clone(),
1615            stdin_writer,
1616            stdout_reader,
1617            None::<async_pipe::PipeReader>,
1618            Arc::new(Mutex::new(None)),
1619            None,
1620            None,
1621            binary.clone(),
1622            root,
1623            Some(workspace_folders.clone()),
1624            cx,
1625            |_| false,
1626        );
1627        server.process_name = process_name;
1628        let fake = FakeLanguageServer {
1629            binary: binary.clone(),
1630            server: Arc::new({
1631                let mut server = LanguageServer::new_internal(
1632                    server_id,
1633                    server_name,
1634                    stdout_writer,
1635                    stdin_reader,
1636                    None::<async_pipe::PipeReader>,
1637                    Arc::new(Mutex::new(None)),
1638                    None,
1639                    None,
1640                    binary,
1641                    Self::root_path(),
1642                    Some(workspace_folders),
1643                    cx,
1644                    move |msg| {
1645                        notifications_tx
1646                            .try_send((
1647                                msg.method.to_string(),
1648                                msg.params.as_ref().unwrap_or(&Value::Null).to_string(),
1649                            ))
1650                            .ok();
1651                        true
1652                    },
1653                );
1654                server.process_name = name.as_str().into();
1655                server
1656            }),
1657            notifications_rx,
1658        };
1659        fake.set_request_handler::<request::Initialize, _, _>({
1660            let capabilities = capabilities;
1661            move |_, _| {
1662                let capabilities = capabilities.clone();
1663                let name = name.clone();
1664                async move {
1665                    Ok(InitializeResult {
1666                        capabilities,
1667                        server_info: Some(ServerInfo {
1668                            name,
1669                            ..Default::default()
1670                        }),
1671                    })
1672                }
1673            }
1674        });
1675
1676        fake.set_request_handler::<request::Shutdown, _, _>(|_, _| async move { Ok(()) });
1677
1678        (server, fake)
1679    }
1680    #[cfg(target_os = "windows")]
1681    fn root_path() -> Url {
1682        Url::from_file_path("C:/").unwrap()
1683    }
1684
1685    #[cfg(not(target_os = "windows"))]
1686    fn root_path() -> Url {
1687        Url::from_file_path("/").unwrap()
1688    }
1689}
1690
1691#[cfg(any(test, feature = "test-support"))]
1692impl LanguageServer {
1693    pub fn full_capabilities() -> ServerCapabilities {
1694        ServerCapabilities {
1695            document_highlight_provider: Some(OneOf::Left(true)),
1696            code_action_provider: Some(CodeActionProviderCapability::Simple(true)),
1697            document_formatting_provider: Some(OneOf::Left(true)),
1698            document_range_formatting_provider: Some(OneOf::Left(true)),
1699            definition_provider: Some(OneOf::Left(true)),
1700            workspace_symbol_provider: Some(OneOf::Left(true)),
1701            implementation_provider: Some(ImplementationProviderCapability::Simple(true)),
1702            type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)),
1703            ..ServerCapabilities::default()
1704        }
1705    }
1706}
1707
1708#[cfg(any(test, feature = "test-support"))]
1709impl FakeLanguageServer {
1710    /// See [`LanguageServer::notify`].
1711    pub fn notify<T: notification::Notification>(&self, params: &T::Params) {
1712        self.server.notify::<T>(params).ok();
1713    }
1714
1715    /// See [`LanguageServer::request`].
1716    pub async fn request<T>(&self, params: T::Params) -> ConnectionResult<T::Result>
1717    where
1718        T: request::Request,
1719        T::Result: 'static + Send,
1720    {
1721        self.server.executor.start_waiting();
1722        self.server.request::<T>(params).await
1723    }
1724
1725    /// Attempts [`Self::try_receive_notification`], unwrapping if it has not received the specified type yet.
1726    pub async fn receive_notification<T: notification::Notification>(&mut self) -> T::Params {
1727        self.server.executor.start_waiting();
1728        self.try_receive_notification::<T>().await.unwrap()
1729    }
1730
1731    /// Consumes the notification channel until it finds a notification for the specified type.
1732    pub async fn try_receive_notification<T: notification::Notification>(
1733        &mut self,
1734    ) -> Option<T::Params> {
1735        loop {
1736            let (method, params) = self.notifications_rx.recv().await.ok()?;
1737            if method == T::METHOD {
1738                return Some(serde_json::from_str::<T::Params>(&params).unwrap());
1739            } else {
1740                log::info!("skipping message in fake language server {:?}", params);
1741            }
1742        }
1743    }
1744
1745    /// Registers a handler for a specific kind of request. Removes any existing handler for specified request type.
1746    pub fn set_request_handler<T, F, Fut>(
1747        &self,
1748        mut handler: F,
1749    ) -> futures::channel::mpsc::UnboundedReceiver<()>
1750    where
1751        T: 'static + request::Request,
1752        T::Params: 'static + Send,
1753        F: 'static + Send + FnMut(T::Params, gpui::AsyncApp) -> Fut,
1754        Fut: 'static + Future<Output = Result<T::Result>>,
1755    {
1756        let (responded_tx, responded_rx) = futures::channel::mpsc::unbounded();
1757        self.server.remove_request_handler::<T>();
1758        self.server
1759            .on_request::<T, _, _>(move |params, cx| {
1760                let result = handler(params, cx.clone());
1761                let responded_tx = responded_tx.clone();
1762                let executor = cx.background_executor().clone();
1763                async move {
1764                    executor.simulate_random_delay().await;
1765                    let result = result.await;
1766                    responded_tx.unbounded_send(()).ok();
1767                    result
1768                }
1769            })
1770            .detach();
1771        responded_rx
1772    }
1773
1774    /// Registers a handler for a specific kind of notification. Removes any existing handler for specified notification type.
1775    pub fn handle_notification<T, F>(
1776        &self,
1777        mut handler: F,
1778    ) -> futures::channel::mpsc::UnboundedReceiver<()>
1779    where
1780        T: 'static + notification::Notification,
1781        T::Params: 'static + Send,
1782        F: 'static + Send + FnMut(T::Params, gpui::AsyncApp),
1783    {
1784        let (handled_tx, handled_rx) = futures::channel::mpsc::unbounded();
1785        self.server.remove_notification_handler::<T>();
1786        self.server
1787            .on_notification::<T, _>(move |params, cx| {
1788                handler(params, cx.clone());
1789                handled_tx.unbounded_send(()).ok();
1790            })
1791            .detach();
1792        handled_rx
1793    }
1794
1795    /// Removes any existing handler for specified notification type.
1796    pub fn remove_request_handler<T>(&mut self)
1797    where
1798        T: 'static + request::Request,
1799    {
1800        self.server.remove_request_handler::<T>();
1801    }
1802
1803    /// Simulate that the server has started work and notifies about its progress with the specified token.
1804    pub async fn start_progress(&self, token: impl Into<String>) {
1805        self.start_progress_with(token, Default::default()).await
1806    }
1807
1808    pub async fn start_progress_with(
1809        &self,
1810        token: impl Into<String>,
1811        progress: WorkDoneProgressBegin,
1812    ) {
1813        let token = token.into();
1814        self.request::<request::WorkDoneProgressCreate>(WorkDoneProgressCreateParams {
1815            token: NumberOrString::String(token.clone()),
1816        })
1817        .await
1818        .into_response()
1819        .unwrap();
1820        self.notify::<notification::Progress>(&ProgressParams {
1821            token: NumberOrString::String(token),
1822            value: ProgressParamsValue::WorkDone(WorkDoneProgress::Begin(progress)),
1823        });
1824    }
1825
1826    /// Simulate that the server has completed work and notifies about that with the specified token.
1827    pub fn end_progress(&self, token: impl Into<String>) {
1828        self.notify::<notification::Progress>(&ProgressParams {
1829            token: NumberOrString::String(token.into()),
1830            value: ProgressParamsValue::WorkDone(WorkDoneProgress::End(Default::default())),
1831        });
1832    }
1833}
1834
1835#[cfg(test)]
1836mod tests {
1837    use super::*;
1838    use gpui::{SemanticVersion, TestAppContext};
1839    use std::str::FromStr;
1840
1841    #[ctor::ctor]
1842    fn init_logger() {
1843        zlog::init_test();
1844    }
1845
1846    #[gpui::test]
1847    async fn test_fake(cx: &mut TestAppContext) {
1848        cx.update(|cx| {
1849            release_channel::init(SemanticVersion::default(), cx);
1850        });
1851        let (server, mut fake) = FakeLanguageServer::new(
1852            LanguageServerId(0),
1853            LanguageServerBinary {
1854                path: "path/to/language-server".into(),
1855                arguments: vec![],
1856                env: None,
1857            },
1858            "the-lsp".to_string(),
1859            Default::default(),
1860            &mut cx.to_async(),
1861        );
1862
1863        let (message_tx, message_rx) = channel::unbounded();
1864        let (diagnostics_tx, diagnostics_rx) = channel::unbounded();
1865        server
1866            .on_notification::<notification::ShowMessage, _>(move |params, _| {
1867                message_tx.try_send(params).unwrap()
1868            })
1869            .detach();
1870        server
1871            .on_notification::<notification::PublishDiagnostics, _>(move |params, _| {
1872                diagnostics_tx.try_send(params).unwrap()
1873            })
1874            .detach();
1875
1876        let server = cx
1877            .update(|cx| {
1878                let params = server.default_initialize_params(false, cx);
1879                let configuration = DidChangeConfigurationParams {
1880                    settings: Default::default(),
1881                };
1882                server.initialize(params, configuration.into(), cx)
1883            })
1884            .await
1885            .unwrap();
1886        server
1887            .notify::<notification::DidOpenTextDocument>(&DidOpenTextDocumentParams {
1888                text_document: TextDocumentItem::new(
1889                    Url::from_str("file://a/b").unwrap(),
1890                    "rust".to_string(),
1891                    0,
1892                    "".to_string(),
1893                ),
1894            })
1895            .unwrap();
1896        assert_eq!(
1897            fake.receive_notification::<notification::DidOpenTextDocument>()
1898                .await
1899                .text_document
1900                .uri
1901                .as_str(),
1902            "file://a/b"
1903        );
1904
1905        fake.notify::<notification::ShowMessage>(&ShowMessageParams {
1906            typ: MessageType::ERROR,
1907            message: "ok".to_string(),
1908        });
1909        fake.notify::<notification::PublishDiagnostics>(&PublishDiagnosticsParams {
1910            uri: Url::from_str("file://b/c").unwrap(),
1911            version: Some(5),
1912            diagnostics: vec![],
1913        });
1914        assert_eq!(message_rx.recv().await.unwrap().message, "ok");
1915        assert_eq!(
1916            diagnostics_rx.recv().await.unwrap().uri.as_str(),
1917            "file://b/c"
1918        );
1919
1920        fake.set_request_handler::<request::Shutdown, _, _>(|_, _| async move { Ok(()) });
1921
1922        drop(server);
1923        fake.receive_notification::<notification::Exit>().await;
1924    }
1925
1926    #[gpui::test]
1927    fn test_deserialize_string_digit_id() {
1928        let json = r#"{"jsonrpc":"2.0","id":"2","method":"workspace/configuration","params":{"items":[{"scopeUri":"file:///Users/mph/Devel/personal/hello-scala/","section":"metals"}]}}"#;
1929        let notification = serde_json::from_str::<NotificationOrRequest>(json)
1930            .expect("message with string id should be parsed");
1931        let expected_id = RequestId::Str("2".to_string());
1932        assert_eq!(notification.id, Some(expected_id));
1933    }
1934
1935    #[gpui::test]
1936    fn test_deserialize_string_id() {
1937        let json = r#"{"jsonrpc":"2.0","id":"anythingAtAll","method":"workspace/configuration","params":{"items":[{"scopeUri":"file:///Users/mph/Devel/personal/hello-scala/","section":"metals"}]}}"#;
1938        let notification = serde_json::from_str::<NotificationOrRequest>(json)
1939            .expect("message with string id should be parsed");
1940        let expected_id = RequestId::Str("anythingAtAll".to_string());
1941        assert_eq!(notification.id, Some(expected_id));
1942    }
1943
1944    #[gpui::test]
1945    fn test_deserialize_int_id() {
1946        let json = r#"{"jsonrpc":"2.0","id":2,"method":"workspace/configuration","params":{"items":[{"scopeUri":"file:///Users/mph/Devel/personal/hello-scala/","section":"metals"}]}}"#;
1947        let notification = serde_json::from_str::<NotificationOrRequest>(json)
1948            .expect("message with string id should be parsed");
1949        let expected_id = RequestId::Int(2);
1950        assert_eq!(notification.id, Some(expected_id));
1951    }
1952
1953    #[test]
1954    fn test_serialize_has_no_nulls() {
1955        // Ensure we're not setting both result and error variants. (ticket #10595)
1956        let no_tag = Response::<u32> {
1957            jsonrpc: "",
1958            id: RequestId::Int(0),
1959            value: LspResult::Ok(None),
1960        };
1961        assert_eq!(
1962            serde_json::to_string(&no_tag).unwrap(),
1963            "{\"jsonrpc\":\"\",\"id\":0,\"result\":null}"
1964        );
1965        let no_tag = Response::<u32> {
1966            jsonrpc: "",
1967            id: RequestId::Int(0),
1968            value: LspResult::Error(None),
1969        };
1970        assert_eq!(
1971            serde_json::to_string(&no_tag).unwrap(),
1972            "{\"jsonrpc\":\"\",\"id\":0,\"error\":null}"
1973        );
1974    }
1975}