lsp.rs

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