lsp.rs

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