lsp.rs

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