lsp.rs

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