lsp_store.rs

   1use crate::{
   2    buffer_store::{BufferStore, BufferStoreEvent},
   3    deserialize_code_actions,
   4    environment::ProjectEnvironment,
   5    lsp_command::{self, *},
   6    lsp_ext_command,
   7    prettier_store::{self, PrettierStore, PrettierStoreEvent},
   8    project_settings::{LspSettings, ProjectSettings},
   9    relativize_path, resolve_path,
  10    worktree_store::{WorktreeStore, WorktreeStoreEvent},
  11    yarn::YarnPathStore,
  12    CodeAction, Completion, CoreCompletion, Hover, InlayHint, Item as _, ProjectPath,
  13    ProjectTransaction, ResolveState, Symbol,
  14};
  15use anyhow::{anyhow, Context as _, Result};
  16use async_trait::async_trait;
  17use client::{proto, TypedEnvelope};
  18use collections::{btree_map, BTreeMap, HashMap, HashSet};
  19use futures::{
  20    future::{join_all, Shared},
  21    select,
  22    stream::FuturesUnordered,
  23    AsyncWriteExt, Future, FutureExt, StreamExt,
  24};
  25use globset::{Glob, GlobSet, GlobSetBuilder};
  26use gpui::{
  27    AppContext, AsyncAppContext, Context, Entity, EventEmitter, Model, ModelContext, PromptLevel,
  28    Task, WeakModel,
  29};
  30use http_client::{BlockedHttpClient, HttpClient};
  31use language::{
  32    language_settings::{
  33        all_language_settings, language_settings, AllLanguageSettings, FormatOnSave, Formatter,
  34        LanguageSettings, SelectedFormatter,
  35    },
  36    markdown, point_to_lsp, prepare_completion_documentation,
  37    proto::{deserialize_anchor, deserialize_version, serialize_anchor, serialize_version},
  38    range_from_lsp, Bias, Buffer, BufferSnapshot, CachedLspAdapter, CodeLabel, Diagnostic,
  39    DiagnosticEntry, DiagnosticSet, Diff, Documentation, File as _, Language, LanguageName,
  40    LanguageRegistry, LanguageServerBinaryStatus, LanguageServerName, LocalFile, LspAdapter,
  41    LspAdapterDelegate, Patch, PointUtf16, TextBufferSnapshot, ToOffset, ToPointUtf16, Transaction,
  42    Unclipped,
  43};
  44use lsp::{
  45    CodeActionKind, CompletionContext, DiagnosticSeverity, DiagnosticTag,
  46    DidChangeWatchedFilesRegistrationOptions, Edit, FileSystemWatcher, InsertTextFormat,
  47    LanguageServer, LanguageServerBinary, LanguageServerBinaryOptions, LanguageServerId,
  48    LspRequestFuture, MessageActionItem, MessageType, OneOf, ServerHealthStatus, ServerStatus,
  49    SymbolKind, TextEdit, Url, WorkDoneProgressCancelParams, WorkspaceFolder,
  50};
  51use node_runtime::read_package_installed_version;
  52use parking_lot::{Mutex, RwLock};
  53use postage::watch;
  54use rand::prelude::*;
  55
  56use rpc::AnyProtoClient;
  57use serde::Serialize;
  58use settings::{Settings, SettingsLocation, SettingsStore};
  59use sha2::{Digest, Sha256};
  60use similar::{ChangeTag, TextDiff};
  61use smol::channel::Sender;
  62use snippet::Snippet;
  63use std::{
  64    any::Any,
  65    cmp::Ordering,
  66    convert::TryInto,
  67    ffi::OsStr,
  68    iter, mem,
  69    ops::{ControlFlow, Range},
  70    path::{self, Path, PathBuf},
  71    str,
  72    sync::Arc,
  73    time::{Duration, Instant},
  74};
  75use text::{Anchor, BufferId, LineEnding};
  76use util::{
  77    debug_panic, defer, maybe, merge_json_value_into, post_inc, ResultExt, TryFutureExt as _,
  78};
  79
  80pub use fs::*;
  81pub use language::Location;
  82#[cfg(any(test, feature = "test-support"))]
  83pub use prettier::FORMAT_SUFFIX as TEST_PRETTIER_FORMAT_SUFFIX;
  84pub use worktree::{
  85    Entry, EntryKind, File, LocalWorktree, PathChange, ProjectEntryId, RepositoryEntry,
  86    UpdatedEntriesSet, UpdatedGitRepositoriesSet, Worktree, WorktreeId, WorktreeSettings,
  87    FS_WATCH_LATENCY,
  88};
  89
  90const SERVER_LAUNCHING_BEFORE_SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(5);
  91pub const SERVER_PROGRESS_THROTTLE_TIMEOUT: Duration = Duration::from_millis(100);
  92
  93#[derive(Debug, Clone, Copy, PartialEq, Eq)]
  94pub enum FormatTrigger {
  95    Save,
  96    Manual,
  97}
  98
  99// Currently, formatting operations are represented differently depending on
 100// whether they come from a language server or an external command.
 101#[derive(Debug)]
 102pub enum FormatOperation {
 103    Lsp(Vec<(Range<Anchor>, String)>),
 104    External(Diff),
 105    Prettier(Diff),
 106}
 107
 108impl FormatTrigger {
 109    fn from_proto(value: i32) -> FormatTrigger {
 110        match value {
 111            0 => FormatTrigger::Save,
 112            1 => FormatTrigger::Manual,
 113            _ => FormatTrigger::Save,
 114        }
 115    }
 116}
 117
 118pub struct LocalLspStore {
 119    http_client: Option<Arc<dyn HttpClient>>,
 120    environment: Model<ProjectEnvironment>,
 121    fs: Arc<dyn Fs>,
 122    yarn: Model<YarnPathStore>,
 123    pub language_servers: HashMap<LanguageServerId, LanguageServerState>,
 124    buffers_being_formatted: HashSet<BufferId>,
 125    last_workspace_edits_by_language_server: HashMap<LanguageServerId, ProjectTransaction>,
 126    language_server_watched_paths: HashMap<LanguageServerId, Model<LanguageServerWatchedPaths>>,
 127    language_server_watcher_registrations:
 128        HashMap<LanguageServerId, HashMap<String, Vec<FileSystemWatcher>>>,
 129    supplementary_language_servers:
 130        HashMap<LanguageServerId, (LanguageServerName, Arc<LanguageServer>)>,
 131    prettier_store: Model<PrettierStore>,
 132    current_lsp_settings: HashMap<LanguageServerName, LspSettings>,
 133    last_formatting_failure: Option<String>,
 134    _subscription: gpui::Subscription,
 135}
 136
 137impl LocalLspStore {
 138    fn shutdown_language_servers(
 139        &mut self,
 140        _cx: &mut ModelContext<LspStore>,
 141    ) -> impl Future<Output = ()> {
 142        let shutdown_futures = self
 143            .language_servers
 144            .drain()
 145            .map(|(_, server_state)| async {
 146                use LanguageServerState::*;
 147                match server_state {
 148                    Running { server, .. } => server.shutdown()?.await,
 149                    Starting(task) => task.await?.shutdown()?.await,
 150                }
 151            })
 152            .collect::<Vec<_>>();
 153
 154        async move {
 155            futures::future::join_all(shutdown_futures).await;
 156        }
 157    }
 158
 159    async fn format_locally(
 160        lsp_store: WeakModel<LspStore>,
 161        mut buffers: Vec<FormattableBuffer>,
 162        push_to_history: bool,
 163        trigger: FormatTrigger,
 164        mut cx: AsyncAppContext,
 165    ) -> anyhow::Result<ProjectTransaction> {
 166        // Do not allow multiple concurrent formatting requests for the
 167        // same buffer.
 168        lsp_store.update(&mut cx, |this, cx| {
 169            let this = this.as_local_mut().unwrap();
 170            buffers.retain(|buffer| {
 171                this.buffers_being_formatted
 172                    .insert(buffer.handle.read(cx).remote_id())
 173            });
 174        })?;
 175
 176        let _cleanup = defer({
 177            let this = lsp_store.clone();
 178            let mut cx = cx.clone();
 179            let buffers = &buffers;
 180            move || {
 181                this.update(&mut cx, |this, cx| {
 182                    let this = this.as_local_mut().unwrap();
 183                    for buffer in buffers {
 184                        this.buffers_being_formatted
 185                            .remove(&buffer.handle.read(cx).remote_id());
 186                    }
 187                })
 188                .ok();
 189            }
 190        });
 191
 192        let mut project_transaction = ProjectTransaction::default();
 193        for buffer in &buffers {
 194            let (primary_adapter_and_server, adapters_and_servers) =
 195                lsp_store.update(&mut cx, |lsp_store, cx| {
 196                    let buffer = buffer.handle.read(cx);
 197
 198                    let adapters_and_servers = lsp_store
 199                        .language_servers_for_buffer(buffer, cx)
 200                        .map(|(adapter, lsp)| (adapter.clone(), lsp.clone()))
 201                        .collect::<Vec<_>>();
 202
 203                    let primary_adapter = lsp_store
 204                        .primary_language_server_for_buffer(buffer, cx)
 205                        .map(|(adapter, lsp)| (adapter.clone(), lsp.clone()));
 206
 207                    (primary_adapter, adapters_and_servers)
 208                })?;
 209
 210            let settings = buffer.handle.update(&mut cx, |buffer, cx| {
 211                language_settings(buffer.language(), buffer.file(), cx).clone()
 212            })?;
 213
 214            let remove_trailing_whitespace = settings.remove_trailing_whitespace_on_save;
 215            let ensure_final_newline = settings.ensure_final_newline_on_save;
 216
 217            // First, format buffer's whitespace according to the settings.
 218            let trailing_whitespace_diff = if remove_trailing_whitespace {
 219                Some(
 220                    buffer
 221                        .handle
 222                        .update(&mut cx, |b, cx| b.remove_trailing_whitespace(cx))?
 223                        .await,
 224                )
 225            } else {
 226                None
 227            };
 228            let whitespace_transaction_id = buffer.handle.update(&mut cx, |buffer, cx| {
 229                buffer.finalize_last_transaction();
 230                buffer.start_transaction();
 231                if let Some(diff) = trailing_whitespace_diff {
 232                    buffer.apply_diff(diff, cx);
 233                }
 234                if ensure_final_newline {
 235                    buffer.ensure_final_newline(cx);
 236                }
 237                buffer.end_transaction(cx)
 238            })?;
 239
 240            // Apply the `code_actions_on_format` before we run the formatter.
 241            let code_actions = deserialize_code_actions(&settings.code_actions_on_format);
 242            #[allow(clippy::nonminimal_bool)]
 243            if !code_actions.is_empty()
 244                && !(trigger == FormatTrigger::Save && settings.format_on_save == FormatOnSave::Off)
 245            {
 246                LspStore::execute_code_actions_on_servers(
 247                    &lsp_store,
 248                    &adapters_and_servers,
 249                    code_actions,
 250                    &buffer.handle,
 251                    push_to_history,
 252                    &mut project_transaction,
 253                    &mut cx,
 254                )
 255                .await?;
 256            }
 257
 258            // Apply language-specific formatting using either the primary language server
 259            // or external command.
 260            // Except for code actions, which are applied with all connected language servers.
 261            let primary_language_server =
 262                primary_adapter_and_server.map(|(_adapter, server)| server.clone());
 263            let server_and_buffer = primary_language_server
 264                .as_ref()
 265                .zip(buffer.abs_path.as_ref());
 266
 267            let prettier_settings = buffer.handle.read_with(&cx, |buffer, cx| {
 268                language_settings(buffer.language(), buffer.file(), cx)
 269                    .prettier
 270                    .clone()
 271            })?;
 272
 273            let mut format_operations: Vec<FormatOperation> = vec![];
 274            {
 275                match trigger {
 276                    FormatTrigger::Save => {
 277                        match &settings.format_on_save {
 278                            FormatOnSave::Off => {
 279                                // nothing
 280                            }
 281                            FormatOnSave::On => {
 282                                match &settings.formatter {
 283                                    SelectedFormatter::Auto => {
 284                                        // do the auto-format: prefer prettier, fallback to primary language server
 285                                        let diff = {
 286                                            if prettier_settings.allowed {
 287                                                Self::perform_format(
 288                                                    &Formatter::Prettier,
 289                                                    server_and_buffer,
 290                                                    lsp_store.clone(),
 291                                                    buffer,
 292                                                    &settings,
 293                                                    &adapters_and_servers,
 294                                                    push_to_history,
 295                                                    &mut project_transaction,
 296                                                    &mut cx,
 297                                                )
 298                                                .await
 299                                            } else {
 300                                                Self::perform_format(
 301                                                    &Formatter::LanguageServer { name: None },
 302                                                    server_and_buffer,
 303                                                    lsp_store.clone(),
 304                                                    buffer,
 305                                                    &settings,
 306                                                    &adapters_and_servers,
 307                                                    push_to_history,
 308                                                    &mut project_transaction,
 309                                                    &mut cx,
 310                                                )
 311                                                .await
 312                                            }
 313                                        }
 314                                        .log_err()
 315                                        .flatten();
 316                                        if let Some(op) = diff {
 317                                            format_operations.push(op);
 318                                        }
 319                                    }
 320                                    SelectedFormatter::List(formatters) => {
 321                                        for formatter in formatters.as_ref() {
 322                                            let diff = Self::perform_format(
 323                                                formatter,
 324                                                server_and_buffer,
 325                                                lsp_store.clone(),
 326                                                buffer,
 327                                                &settings,
 328                                                &adapters_and_servers,
 329                                                push_to_history,
 330                                                &mut project_transaction,
 331                                                &mut cx,
 332                                            )
 333                                            .await
 334                                            .log_err()
 335                                            .flatten();
 336                                            if let Some(op) = diff {
 337                                                format_operations.push(op);
 338                                            }
 339
 340                                            // format with formatter
 341                                        }
 342                                    }
 343                                }
 344                            }
 345                            FormatOnSave::List(formatters) => {
 346                                for formatter in formatters.as_ref() {
 347                                    let diff = Self::perform_format(
 348                                        formatter,
 349                                        server_and_buffer,
 350                                        lsp_store.clone(),
 351                                        buffer,
 352                                        &settings,
 353                                        &adapters_and_servers,
 354                                        push_to_history,
 355                                        &mut project_transaction,
 356                                        &mut cx,
 357                                    )
 358                                    .await
 359                                    .log_err()
 360                                    .flatten();
 361                                    if let Some(op) = diff {
 362                                        format_operations.push(op);
 363                                    }
 364                                }
 365                            }
 366                        }
 367                    }
 368                    FormatTrigger::Manual => {
 369                        match &settings.formatter {
 370                            SelectedFormatter::Auto => {
 371                                // do the auto-format: prefer prettier, fallback to primary language server
 372                                let diff = {
 373                                    if prettier_settings.allowed {
 374                                        Self::perform_format(
 375                                            &Formatter::Prettier,
 376                                            server_and_buffer,
 377                                            lsp_store.clone(),
 378                                            buffer,
 379                                            &settings,
 380                                            &adapters_and_servers,
 381                                            push_to_history,
 382                                            &mut project_transaction,
 383                                            &mut cx,
 384                                        )
 385                                        .await
 386                                    } else {
 387                                        Self::perform_format(
 388                                            &Formatter::LanguageServer { name: None },
 389                                            server_and_buffer,
 390                                            lsp_store.clone(),
 391                                            buffer,
 392                                            &settings,
 393                                            &adapters_and_servers,
 394                                            push_to_history,
 395                                            &mut project_transaction,
 396                                            &mut cx,
 397                                        )
 398                                        .await
 399                                    }
 400                                }
 401                                .log_err()
 402                                .flatten();
 403
 404                                if let Some(op) = diff {
 405                                    format_operations.push(op)
 406                                }
 407                            }
 408                            SelectedFormatter::List(formatters) => {
 409                                for formatter in formatters.as_ref() {
 410                                    // format with formatter
 411                                    let diff = Self::perform_format(
 412                                        formatter,
 413                                        server_and_buffer,
 414                                        lsp_store.clone(),
 415                                        buffer,
 416                                        &settings,
 417                                        &adapters_and_servers,
 418                                        push_to_history,
 419                                        &mut project_transaction,
 420                                        &mut cx,
 421                                    )
 422                                    .await
 423                                    .log_err()
 424                                    .flatten();
 425                                    if let Some(op) = diff {
 426                                        format_operations.push(op);
 427                                    }
 428                                }
 429                            }
 430                        }
 431                    }
 432                }
 433            }
 434
 435            buffer.handle.update(&mut cx, |b, cx| {
 436                // If the buffer had its whitespace formatted and was edited while the language-specific
 437                // formatting was being computed, avoid applying the language-specific formatting, because
 438                // it can't be grouped with the whitespace formatting in the undo history.
 439                if let Some(transaction_id) = whitespace_transaction_id {
 440                    if b.peek_undo_stack()
 441                        .map_or(true, |e| e.transaction_id() != transaction_id)
 442                    {
 443                        format_operations.clear();
 444                    }
 445                }
 446
 447                // Apply any language-specific formatting, and group the two formatting operations
 448                // in the buffer's undo history.
 449                for operation in format_operations {
 450                    match operation {
 451                        FormatOperation::Lsp(edits) => {
 452                            b.edit(edits, None, cx);
 453                        }
 454                        FormatOperation::External(diff) => {
 455                            b.apply_diff(diff, cx);
 456                        }
 457                        FormatOperation::Prettier(diff) => {
 458                            b.apply_diff(diff, cx);
 459                        }
 460                    }
 461
 462                    if let Some(transaction_id) = whitespace_transaction_id {
 463                        b.group_until_transaction(transaction_id);
 464                    } else if let Some(transaction) = project_transaction.0.get(&buffer.handle) {
 465                        b.group_until_transaction(transaction.id)
 466                    }
 467                }
 468
 469                if let Some(transaction) = b.finalize_last_transaction().cloned() {
 470                    if !push_to_history {
 471                        b.forget_transaction(transaction.id);
 472                    }
 473                    project_transaction
 474                        .0
 475                        .insert(buffer.handle.clone(), transaction);
 476                }
 477            })?;
 478        }
 479
 480        Ok(project_transaction)
 481    }
 482
 483    #[allow(clippy::too_many_arguments)]
 484    async fn perform_format(
 485        formatter: &Formatter,
 486        primary_server_and_buffer: Option<(&Arc<LanguageServer>, &PathBuf)>,
 487        lsp_store: WeakModel<LspStore>,
 488        buffer: &FormattableBuffer,
 489        settings: &LanguageSettings,
 490        adapters_and_servers: &[(Arc<CachedLspAdapter>, Arc<LanguageServer>)],
 491        push_to_history: bool,
 492        transaction: &mut ProjectTransaction,
 493        cx: &mut AsyncAppContext,
 494    ) -> Result<Option<FormatOperation>, anyhow::Error> {
 495        let result = match formatter {
 496            Formatter::LanguageServer { name } => {
 497                if let Some((language_server, buffer_abs_path)) = primary_server_and_buffer {
 498                    let language_server = if let Some(name) = name {
 499                        adapters_and_servers
 500                            .iter()
 501                            .find_map(|(adapter, server)| {
 502                                adapter.name.0.as_ref().eq(name.as_str()).then_some(server)
 503                            })
 504                            .unwrap_or(language_server)
 505                    } else {
 506                        language_server
 507                    };
 508
 509                    Some(FormatOperation::Lsp(
 510                        LspStore::format_via_lsp(
 511                            &lsp_store,
 512                            &buffer.handle,
 513                            buffer_abs_path,
 514                            language_server,
 515                            settings,
 516                            cx,
 517                        )
 518                        .await
 519                        .context("failed to format via language server")?,
 520                    ))
 521                } else {
 522                    None
 523                }
 524            }
 525            Formatter::Prettier => {
 526                let prettier = lsp_store.update(cx, |lsp_store, _cx| {
 527                    lsp_store.prettier_store().unwrap().downgrade()
 528                })?;
 529                prettier_store::format_with_prettier(&prettier, &buffer.handle, cx)
 530                    .await
 531                    .transpose()
 532                    .ok()
 533                    .flatten()
 534            }
 535            Formatter::External { command, arguments } => {
 536                Self::format_via_external_command(buffer, command, arguments.as_deref(), cx)
 537                    .await
 538                    .context(format!(
 539                        "failed to format via external command {:?}",
 540                        command
 541                    ))?
 542                    .map(FormatOperation::External)
 543            }
 544            Formatter::CodeActions(code_actions) => {
 545                let code_actions = deserialize_code_actions(code_actions);
 546                if !code_actions.is_empty() {
 547                    LspStore::execute_code_actions_on_servers(
 548                        &lsp_store,
 549                        adapters_and_servers,
 550                        code_actions,
 551                        &buffer.handle,
 552                        push_to_history,
 553                        transaction,
 554                        cx,
 555                    )
 556                    .await?;
 557                }
 558                None
 559            }
 560        };
 561        anyhow::Ok(result)
 562    }
 563
 564    async fn format_via_external_command(
 565        buffer: &FormattableBuffer,
 566        command: &str,
 567        arguments: Option<&[String]>,
 568        cx: &mut AsyncAppContext,
 569    ) -> Result<Option<Diff>> {
 570        let working_dir_path = buffer.handle.update(cx, |buffer, cx| {
 571            let file = File::from_dyn(buffer.file())?;
 572            let worktree = file.worktree.read(cx);
 573            let mut worktree_path = worktree.abs_path().to_path_buf();
 574            if worktree.root_entry()?.is_file() {
 575                worktree_path.pop();
 576            }
 577            Some(worktree_path)
 578        })?;
 579
 580        let mut child = smol::process::Command::new(command);
 581        #[cfg(target_os = "windows")]
 582        {
 583            use smol::process::windows::CommandExt;
 584            child.creation_flags(windows::Win32::System::Threading::CREATE_NO_WINDOW.0);
 585        }
 586
 587        if let Some(buffer_env) = buffer.env.as_ref() {
 588            child.envs(buffer_env);
 589        }
 590
 591        if let Some(working_dir_path) = working_dir_path {
 592            child.current_dir(working_dir_path);
 593        }
 594
 595        if let Some(arguments) = arguments {
 596            child.args(arguments.iter().map(|arg| {
 597                if let Some(buffer_abs_path) = buffer.abs_path.as_ref() {
 598                    arg.replace("{buffer_path}", &buffer_abs_path.to_string_lossy())
 599                } else {
 600                    arg.replace("{buffer_path}", "Untitled")
 601                }
 602            }));
 603        }
 604
 605        let mut child = child
 606            .stdin(smol::process::Stdio::piped())
 607            .stdout(smol::process::Stdio::piped())
 608            .stderr(smol::process::Stdio::piped())
 609            .spawn()?;
 610
 611        let stdin = child
 612            .stdin
 613            .as_mut()
 614            .ok_or_else(|| anyhow!("failed to acquire stdin"))?;
 615        let text = buffer
 616            .handle
 617            .update(cx, |buffer, _| buffer.as_rope().clone())?;
 618        for chunk in text.chunks() {
 619            stdin.write_all(chunk.as_bytes()).await?;
 620        }
 621        stdin.flush().await?;
 622
 623        let output = child.output().await?;
 624        if !output.status.success() {
 625            return Err(anyhow!(
 626                "command failed with exit code {:?}:\nstdout: {}\nstderr: {}",
 627                output.status.code(),
 628                String::from_utf8_lossy(&output.stdout),
 629                String::from_utf8_lossy(&output.stderr),
 630            ));
 631        }
 632
 633        let stdout = String::from_utf8(output.stdout)?;
 634        Ok(Some(
 635            buffer
 636                .handle
 637                .update(cx, |buffer, cx| buffer.diff(stdout, cx))?
 638                .await,
 639        ))
 640    }
 641}
 642
 643pub struct FormattableBuffer {
 644    handle: Model<Buffer>,
 645    abs_path: Option<PathBuf>,
 646    env: Option<HashMap<String, String>>,
 647}
 648
 649pub struct RemoteLspStore {
 650    upstream_client: Option<AnyProtoClient>,
 651    upstream_project_id: u64,
 652}
 653
 654#[allow(clippy::large_enum_variant)]
 655pub enum LspStoreMode {
 656    Local(LocalLspStore),   // ssh host and collab host
 657    Remote(RemoteLspStore), // collab guest
 658}
 659
 660impl LspStoreMode {
 661    fn is_local(&self) -> bool {
 662        matches!(self, LspStoreMode::Local(_))
 663    }
 664
 665    fn is_remote(&self) -> bool {
 666        matches!(self, LspStoreMode::Remote(_))
 667    }
 668}
 669
 670pub struct LspStore {
 671    mode: LspStoreMode,
 672    downstream_client: Option<(AnyProtoClient, u64)>,
 673    nonce: u128,
 674    buffer_store: Model<BufferStore>,
 675    worktree_store: Model<WorktreeStore>,
 676    buffer_snapshots: HashMap<BufferId, HashMap<LanguageServerId, Vec<LspBufferSnapshot>>>, // buffer_id -> server_id -> vec of snapshots
 677    pub languages: Arc<LanguageRegistry>,
 678    language_server_ids: HashMap<(WorktreeId, LanguageServerName), LanguageServerId>,
 679    pub language_server_statuses: BTreeMap<LanguageServerId, LanguageServerStatus>,
 680    active_entry: Option<ProjectEntryId>,
 681    _maintain_workspace_config: Task<Result<()>>,
 682    _maintain_buffer_languages: Task<()>,
 683    next_diagnostic_group_id: usize,
 684    diagnostic_summaries:
 685        HashMap<WorktreeId, HashMap<Arc<Path>, HashMap<LanguageServerId, DiagnosticSummary>>>,
 686    diagnostics: HashMap<
 687        WorktreeId,
 688        HashMap<
 689            Arc<Path>,
 690            Vec<(
 691                LanguageServerId,
 692                Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
 693            )>,
 694        >,
 695    >,
 696}
 697
 698pub enum LspStoreEvent {
 699    LanguageServerAdded(LanguageServerId),
 700    LanguageServerRemoved(LanguageServerId),
 701    LanguageServerUpdate {
 702        language_server_id: LanguageServerId,
 703        message: proto::update_language_server::Variant,
 704    },
 705    LanguageServerLog(LanguageServerId, LanguageServerLogType, String),
 706    LanguageServerPrompt(LanguageServerPromptRequest),
 707    LanguageDetected {
 708        buffer: Model<Buffer>,
 709        new_language: Option<Arc<Language>>,
 710    },
 711    Notification(String),
 712    RefreshInlayHints,
 713    DiagnosticsUpdated {
 714        language_server_id: LanguageServerId,
 715        path: ProjectPath,
 716    },
 717    DiskBasedDiagnosticsStarted {
 718        language_server_id: LanguageServerId,
 719    },
 720    DiskBasedDiagnosticsFinished {
 721        language_server_id: LanguageServerId,
 722    },
 723    SnippetEdit {
 724        buffer_id: BufferId,
 725        edits: Vec<(lsp::Range, Snippet)>,
 726        most_recent_edit: clock::Lamport,
 727    },
 728}
 729
 730#[derive(Clone, Debug, Serialize)]
 731pub struct LanguageServerStatus {
 732    pub name: String,
 733    pub pending_work: BTreeMap<String, LanguageServerProgress>,
 734    pub has_pending_diagnostic_updates: bool,
 735    progress_tokens: HashSet<String>,
 736}
 737
 738#[derive(Clone, Debug)]
 739struct CoreSymbol {
 740    pub language_server_name: LanguageServerName,
 741    pub source_worktree_id: WorktreeId,
 742    pub path: ProjectPath,
 743    pub name: String,
 744    pub kind: lsp::SymbolKind,
 745    pub range: Range<Unclipped<PointUtf16>>,
 746    pub signature: [u8; 32],
 747}
 748
 749impl LspStore {
 750    pub fn init(client: &AnyProtoClient) {
 751        client.add_model_request_handler(Self::handle_multi_lsp_query);
 752        client.add_model_request_handler(Self::handle_restart_language_servers);
 753        client.add_model_message_handler(Self::handle_start_language_server);
 754        client.add_model_message_handler(Self::handle_update_language_server);
 755        client.add_model_message_handler(Self::handle_update_diagnostic_summary);
 756        client.add_model_request_handler(Self::handle_format_buffers);
 757        client.add_model_request_handler(Self::handle_resolve_completion_documentation);
 758        client.add_model_request_handler(Self::handle_apply_code_action);
 759        client.add_model_request_handler(Self::handle_inlay_hints);
 760        client.add_model_request_handler(Self::handle_get_project_symbols);
 761        client.add_model_request_handler(Self::handle_resolve_inlay_hint);
 762        client.add_model_request_handler(Self::handle_open_buffer_for_symbol);
 763        client.add_model_request_handler(Self::handle_refresh_inlay_hints);
 764        client.add_model_request_handler(Self::handle_on_type_formatting);
 765        client.add_model_request_handler(Self::handle_apply_additional_edits_for_completion);
 766        client.add_model_request_handler(Self::handle_lsp_command::<GetCodeActions>);
 767        client.add_model_request_handler(Self::handle_lsp_command::<GetCompletions>);
 768        client.add_model_request_handler(Self::handle_lsp_command::<GetHover>);
 769        client.add_model_request_handler(Self::handle_lsp_command::<GetDefinition>);
 770        client.add_model_request_handler(Self::handle_lsp_command::<GetDeclaration>);
 771        client.add_model_request_handler(Self::handle_lsp_command::<GetTypeDefinition>);
 772        client.add_model_request_handler(Self::handle_lsp_command::<GetDocumentHighlights>);
 773        client.add_model_request_handler(Self::handle_lsp_command::<GetReferences>);
 774        client.add_model_request_handler(Self::handle_lsp_command::<PrepareRename>);
 775        client.add_model_request_handler(Self::handle_lsp_command::<PerformRename>);
 776        client.add_model_request_handler(Self::handle_lsp_command::<lsp_ext_command::ExpandMacro>);
 777        client.add_model_request_handler(Self::handle_lsp_command::<LinkedEditingRange>);
 778    }
 779
 780    pub fn as_remote(&self) -> Option<&RemoteLspStore> {
 781        match &self.mode {
 782            LspStoreMode::Remote(remote_lsp_store) => Some(remote_lsp_store),
 783            _ => None,
 784        }
 785    }
 786
 787    pub fn as_local(&self) -> Option<&LocalLspStore> {
 788        match &self.mode {
 789            LspStoreMode::Local(local_lsp_store) => Some(local_lsp_store),
 790            _ => None,
 791        }
 792    }
 793
 794    pub fn as_local_mut(&mut self) -> Option<&mut LocalLspStore> {
 795        match &mut self.mode {
 796            LspStoreMode::Local(local_lsp_store) => Some(local_lsp_store),
 797            _ => None,
 798        }
 799    }
 800
 801    pub fn upstream_client(&self) -> Option<(AnyProtoClient, u64)> {
 802        match &self.mode {
 803            LspStoreMode::Remote(RemoteLspStore {
 804                upstream_client: Some(upstream_client),
 805                upstream_project_id,
 806                ..
 807            }) => Some((upstream_client.clone(), *upstream_project_id)),
 808
 809            LspStoreMode::Remote(RemoteLspStore {
 810                upstream_client: None,
 811                ..
 812            }) => None,
 813            LspStoreMode::Local(_) => None,
 814        }
 815    }
 816
 817    pub fn swap_current_lsp_settings(
 818        &mut self,
 819        new_settings: HashMap<LanguageServerName, LspSettings>,
 820    ) -> Option<HashMap<LanguageServerName, LspSettings>> {
 821        match &mut self.mode {
 822            LspStoreMode::Local(LocalLspStore {
 823                current_lsp_settings,
 824                ..
 825            }) => {
 826                let ret = mem::take(current_lsp_settings);
 827                *current_lsp_settings = new_settings;
 828                Some(ret)
 829            }
 830            LspStoreMode::Remote(_) => None,
 831        }
 832    }
 833
 834    #[allow(clippy::too_many_arguments)]
 835    pub fn new_local(
 836        buffer_store: Model<BufferStore>,
 837        worktree_store: Model<WorktreeStore>,
 838        prettier_store: Model<PrettierStore>,
 839        environment: Model<ProjectEnvironment>,
 840        languages: Arc<LanguageRegistry>,
 841        http_client: Option<Arc<dyn HttpClient>>,
 842        fs: Arc<dyn Fs>,
 843        cx: &mut ModelContext<Self>,
 844    ) -> Self {
 845        let yarn = YarnPathStore::new(fs.clone(), cx);
 846        cx.subscribe(&buffer_store, Self::on_buffer_store_event)
 847            .detach();
 848        cx.subscribe(&worktree_store, Self::on_worktree_store_event)
 849            .detach();
 850        cx.subscribe(&prettier_store, Self::on_prettier_store_event)
 851            .detach();
 852        cx.observe_global::<SettingsStore>(Self::on_settings_changed)
 853            .detach();
 854
 855        Self {
 856            mode: LspStoreMode::Local(LocalLspStore {
 857                supplementary_language_servers: Default::default(),
 858                language_servers: Default::default(),
 859                last_workspace_edits_by_language_server: Default::default(),
 860                language_server_watched_paths: Default::default(),
 861                language_server_watcher_registrations: Default::default(),
 862                current_lsp_settings: ProjectSettings::get_global(cx).lsp.clone(),
 863                buffers_being_formatted: Default::default(),
 864                last_formatting_failure: None,
 865                prettier_store,
 866                environment,
 867                http_client,
 868                fs,
 869                yarn,
 870                _subscription: cx.on_app_quit(|this, cx| {
 871                    this.as_local_mut().unwrap().shutdown_language_servers(cx)
 872                }),
 873            }),
 874            downstream_client: None,
 875            buffer_store,
 876            worktree_store,
 877            languages: languages.clone(),
 878            language_server_ids: Default::default(),
 879            language_server_statuses: Default::default(),
 880            nonce: StdRng::from_entropy().gen(),
 881            buffer_snapshots: Default::default(),
 882            next_diagnostic_group_id: Default::default(),
 883            diagnostic_summaries: Default::default(),
 884            diagnostics: Default::default(),
 885            active_entry: None,
 886
 887            _maintain_workspace_config: Self::maintain_workspace_config(cx),
 888            _maintain_buffer_languages: Self::maintain_buffer_languages(languages.clone(), cx),
 889        }
 890    }
 891
 892    fn send_lsp_proto_request<R: LspCommand>(
 893        &self,
 894        buffer: Model<Buffer>,
 895        client: AnyProtoClient,
 896        upstream_project_id: u64,
 897        request: R,
 898        cx: &mut ModelContext<'_, LspStore>,
 899    ) -> Task<anyhow::Result<<R as LspCommand>::Response>> {
 900        let message = request.to_proto(upstream_project_id, buffer.read(cx));
 901        cx.spawn(move |this, cx| async move {
 902            let response = client.request(message).await?;
 903            let this = this.upgrade().context("project dropped")?;
 904            request
 905                .response_from_proto(response, this, buffer, cx)
 906                .await
 907        })
 908    }
 909
 910    pub fn new_remote(
 911        buffer_store: Model<BufferStore>,
 912        worktree_store: Model<WorktreeStore>,
 913        languages: Arc<LanguageRegistry>,
 914        upstream_client: AnyProtoClient,
 915        project_id: u64,
 916        cx: &mut ModelContext<Self>,
 917    ) -> Self {
 918        cx.subscribe(&buffer_store, Self::on_buffer_store_event)
 919            .detach();
 920        cx.subscribe(&worktree_store, Self::on_worktree_store_event)
 921            .detach();
 922
 923        Self {
 924            mode: LspStoreMode::Remote(RemoteLspStore {
 925                upstream_client: Some(upstream_client),
 926                upstream_project_id: project_id,
 927            }),
 928            downstream_client: None,
 929            buffer_store,
 930            worktree_store,
 931            languages: languages.clone(),
 932            language_server_ids: Default::default(),
 933            language_server_statuses: Default::default(),
 934            nonce: StdRng::from_entropy().gen(),
 935            buffer_snapshots: Default::default(),
 936            next_diagnostic_group_id: Default::default(),
 937            diagnostic_summaries: Default::default(),
 938            diagnostics: Default::default(),
 939            active_entry: None,
 940            _maintain_workspace_config: Self::maintain_workspace_config(cx),
 941            _maintain_buffer_languages: Self::maintain_buffer_languages(languages.clone(), cx),
 942        }
 943    }
 944
 945    fn worktree_for_id(
 946        &self,
 947        worktree_id: WorktreeId,
 948        cx: &ModelContext<Self>,
 949    ) -> Result<Model<Worktree>> {
 950        self.worktree_store
 951            .read(cx)
 952            .worktree_for_id(worktree_id, cx)
 953            .ok_or_else(|| anyhow!("worktree not found"))
 954    }
 955
 956    fn on_buffer_store_event(
 957        &mut self,
 958        _: Model<BufferStore>,
 959        event: &BufferStoreEvent,
 960        cx: &mut ModelContext<Self>,
 961    ) {
 962        match event {
 963            BufferStoreEvent::BufferAdded(buffer) => {
 964                self.register_buffer(buffer, cx).log_err();
 965            }
 966            BufferStoreEvent::BufferChangedFilePath { buffer, old_file } => {
 967                if let Some(old_file) = File::from_dyn(old_file.as_ref()) {
 968                    self.unregister_buffer_from_language_servers(buffer, old_file, cx);
 969                }
 970
 971                self.register_buffer_with_language_servers(buffer, cx);
 972            }
 973            BufferStoreEvent::BufferDropped(_) => {}
 974        }
 975    }
 976
 977    fn on_worktree_store_event(
 978        &mut self,
 979        _: Model<WorktreeStore>,
 980        event: &WorktreeStoreEvent,
 981        cx: &mut ModelContext<Self>,
 982    ) {
 983        match event {
 984            WorktreeStoreEvent::WorktreeAdded(worktree) => {
 985                if !worktree.read(cx).is_local() {
 986                    return;
 987                }
 988                cx.subscribe(worktree, |this, worktree, event, cx| match event {
 989                    worktree::Event::UpdatedEntries(changes) => {
 990                        this.update_local_worktree_language_servers(&worktree, changes, cx);
 991                    }
 992                    worktree::Event::UpdatedGitRepositories(_)
 993                    | worktree::Event::DeletedEntry(_) => {}
 994                })
 995                .detach()
 996            }
 997            WorktreeStoreEvent::WorktreeRemoved(_, id) => self.remove_worktree(*id, cx),
 998            WorktreeStoreEvent::WorktreeOrderChanged => {}
 999            WorktreeStoreEvent::WorktreeUpdateSent(worktree) => {
1000                worktree.update(cx, |worktree, _cx| self.send_diagnostic_summaries(worktree));
1001            }
1002        }
1003    }
1004
1005    fn on_prettier_store_event(
1006        &mut self,
1007        _: Model<PrettierStore>,
1008        event: &PrettierStoreEvent,
1009        cx: &mut ModelContext<Self>,
1010    ) {
1011        match event {
1012            PrettierStoreEvent::LanguageServerRemoved(prettier_server_id) => {
1013                self.unregister_supplementary_language_server(*prettier_server_id, cx);
1014            }
1015            PrettierStoreEvent::LanguageServerAdded {
1016                new_server_id,
1017                name,
1018                prettier_server,
1019            } => {
1020                self.register_supplementary_language_server(
1021                    *new_server_id,
1022                    name.clone(),
1023                    prettier_server.clone(),
1024                    cx,
1025                );
1026            }
1027        }
1028    }
1029
1030    // todo!
1031    pub fn prettier_store(&self) -> Option<Model<PrettierStore>> {
1032        self.as_local().map(|local| local.prettier_store.clone())
1033    }
1034
1035    fn on_buffer_event(
1036        &mut self,
1037        buffer: Model<Buffer>,
1038        event: &language::BufferEvent,
1039        cx: &mut ModelContext<Self>,
1040    ) {
1041        match event {
1042            language::BufferEvent::Edited { .. } => {
1043                self.on_buffer_edited(buffer, cx);
1044            }
1045
1046            language::BufferEvent::Saved => {
1047                self.on_buffer_saved(buffer, cx);
1048            }
1049
1050            _ => {}
1051        }
1052    }
1053
1054    fn register_buffer(
1055        &mut self,
1056        buffer: &Model<Buffer>,
1057        cx: &mut ModelContext<Self>,
1058    ) -> Result<()> {
1059        buffer.update(cx, |buffer, _| {
1060            buffer.set_language_registry(self.languages.clone())
1061        });
1062
1063        cx.subscribe(buffer, |this, buffer, event, cx| {
1064            this.on_buffer_event(buffer, event, cx);
1065        })
1066        .detach();
1067
1068        self.register_buffer_with_language_servers(buffer, cx);
1069        cx.observe_release(buffer, |this, buffer, cx| {
1070            if let Some(file) = File::from_dyn(buffer.file()) {
1071                if file.is_local() {
1072                    let uri = lsp::Url::from_file_path(file.abs_path(cx)).unwrap();
1073                    for server in this.language_servers_for_buffer(buffer, cx) {
1074                        server
1075                            .1
1076                            .notify::<lsp::notification::DidCloseTextDocument>(
1077                                lsp::DidCloseTextDocumentParams {
1078                                    text_document: lsp::TextDocumentIdentifier::new(uri.clone()),
1079                                },
1080                            )
1081                            .log_err();
1082                    }
1083                }
1084            }
1085        })
1086        .detach();
1087
1088        Ok(())
1089    }
1090
1091    fn maintain_buffer_languages(
1092        languages: Arc<LanguageRegistry>,
1093        cx: &mut ModelContext<Self>,
1094    ) -> Task<()> {
1095        let mut subscription = languages.subscribe();
1096        let mut prev_reload_count = languages.reload_count();
1097        cx.spawn(move |this, mut cx| async move {
1098            while let Some(()) = subscription.next().await {
1099                if let Some(this) = this.upgrade() {
1100                    // If the language registry has been reloaded, then remove and
1101                    // re-assign the languages on all open buffers.
1102                    let reload_count = languages.reload_count();
1103                    if reload_count > prev_reload_count {
1104                        prev_reload_count = reload_count;
1105                        this.update(&mut cx, |this, cx| {
1106                            this.buffer_store.clone().update(cx, |buffer_store, cx| {
1107                                for buffer in buffer_store.buffers() {
1108                                    if let Some(f) = File::from_dyn(buffer.read(cx).file()).cloned()
1109                                    {
1110                                        this.unregister_buffer_from_language_servers(
1111                                            &buffer, &f, cx,
1112                                        );
1113                                        buffer
1114                                            .update(cx, |buffer, cx| buffer.set_language(None, cx));
1115                                    }
1116                                }
1117                            });
1118                        })
1119                        .ok();
1120                    }
1121
1122                    this.update(&mut cx, |this, cx| {
1123                        let mut plain_text_buffers = Vec::new();
1124                        let mut buffers_with_unknown_injections = Vec::new();
1125                        for handle in this.buffer_store.read(cx).buffers() {
1126                            let buffer = handle.read(cx);
1127                            if buffer.language().is_none()
1128                                || buffer.language() == Some(&*language::PLAIN_TEXT)
1129                            {
1130                                plain_text_buffers.push(handle);
1131                            } else if buffer.contains_unknown_injections() {
1132                                buffers_with_unknown_injections.push(handle);
1133                            }
1134                        }
1135                        for buffer in plain_text_buffers {
1136                            this.register_buffer_with_language_servers(&buffer, cx);
1137                        }
1138
1139                        for buffer in buffers_with_unknown_injections {
1140                            buffer.update(cx, |buffer, cx| buffer.reparse(cx));
1141                        }
1142                    })
1143                    .ok();
1144                }
1145            }
1146        })
1147    }
1148
1149    fn detect_language_for_buffer(
1150        &mut self,
1151        buffer_handle: &Model<Buffer>,
1152        cx: &mut ModelContext<Self>,
1153    ) -> Option<language::AvailableLanguage> {
1154        // If the buffer has a language, set it and start the language server if we haven't already.
1155        let buffer = buffer_handle.read(cx);
1156        let file = buffer.file()?;
1157
1158        let content = buffer.as_rope();
1159        let available_language = self.languages.language_for_file(file, Some(content), cx);
1160        if let Some(available_language) = &available_language {
1161            if let Some(Ok(Ok(new_language))) = self
1162                .languages
1163                .load_language(available_language)
1164                .now_or_never()
1165            {
1166                self.set_language_for_buffer(buffer_handle, new_language, cx);
1167            }
1168        } else {
1169            cx.emit(LspStoreEvent::LanguageDetected {
1170                buffer: buffer_handle.clone(),
1171                new_language: None,
1172            });
1173        }
1174
1175        available_language
1176    }
1177
1178    pub fn set_language_for_buffer(
1179        &mut self,
1180        buffer: &Model<Buffer>,
1181        new_language: Arc<Language>,
1182        cx: &mut ModelContext<Self>,
1183    ) {
1184        buffer.update(cx, |buffer, cx| {
1185            if buffer.language().map_or(true, |old_language| {
1186                !Arc::ptr_eq(old_language, &new_language)
1187            }) {
1188                buffer.set_language(Some(new_language.clone()), cx);
1189            }
1190        });
1191
1192        let buffer_file = buffer.read(cx).file().cloned();
1193        let settings = language_settings(Some(&new_language), buffer_file.as_ref(), cx).clone();
1194        let buffer_file = File::from_dyn(buffer_file.as_ref());
1195
1196        let worktree_id = if let Some(file) = buffer_file {
1197            let worktree = file.worktree.clone();
1198            self.start_language_servers(&worktree, new_language.name(), cx);
1199
1200            Some(worktree.read(cx).id())
1201        } else {
1202            None
1203        };
1204
1205        if let Some(prettier_plugins) = prettier_store::prettier_plugins_for_language(&settings) {
1206            let prettier_store = self.as_local().map(|s| s.prettier_store.clone());
1207            if let Some(prettier_store) = prettier_store {
1208                prettier_store.update(cx, |prettier_store, cx| {
1209                    prettier_store.install_default_prettier(
1210                        worktree_id,
1211                        prettier_plugins.iter().map(|s| Arc::from(s.as_str())),
1212                        cx,
1213                    )
1214                })
1215            }
1216        }
1217
1218        cx.emit(LspStoreEvent::LanguageDetected {
1219            buffer: buffer.clone(),
1220            new_language: Some(new_language),
1221        })
1222    }
1223
1224    pub fn buffer_store(&self) -> Model<BufferStore> {
1225        self.buffer_store.clone()
1226    }
1227
1228    pub fn set_active_entry(&mut self, active_entry: Option<ProjectEntryId>) {
1229        self.active_entry = active_entry;
1230    }
1231
1232    pub(crate) fn send_diagnostic_summaries(&self, worktree: &mut Worktree) {
1233        if let Some((client, downstream_project_id)) = self.downstream_client.clone() {
1234            if let Some(summaries) = self.diagnostic_summaries.get(&worktree.id()) {
1235                for (path, summaries) in summaries {
1236                    for (&server_id, summary) in summaries {
1237                        client
1238                            .send(proto::UpdateDiagnosticSummary {
1239                                project_id: downstream_project_id,
1240                                worktree_id: worktree.id().to_proto(),
1241                                summary: Some(summary.to_proto(server_id, path)),
1242                            })
1243                            .log_err();
1244                    }
1245                }
1246            }
1247        }
1248    }
1249
1250    pub fn request_lsp<R: LspCommand>(
1251        &self,
1252        buffer_handle: Model<Buffer>,
1253        server: LanguageServerToQuery,
1254        request: R,
1255        cx: &mut ModelContext<Self>,
1256    ) -> Task<Result<R::Response>>
1257    where
1258        <R::LspRequest as lsp::request::Request>::Result: Send,
1259        <R::LspRequest as lsp::request::Request>::Params: Send,
1260    {
1261        let buffer = buffer_handle.read(cx);
1262
1263        if let Some((upstream_client, upstream_project_id)) = self.upstream_client() {
1264            return self.send_lsp_proto_request(
1265                buffer_handle,
1266                upstream_client,
1267                upstream_project_id,
1268                request,
1269                cx,
1270            );
1271        }
1272
1273        let language_server = match server {
1274            LanguageServerToQuery::Primary => {
1275                match self.primary_language_server_for_buffer(buffer, cx) {
1276                    Some((_, server)) => Some(Arc::clone(server)),
1277                    None => return Task::ready(Ok(Default::default())),
1278                }
1279            }
1280            LanguageServerToQuery::Other(id) => self
1281                .language_server_for_buffer(buffer, id, cx)
1282                .map(|(_, server)| Arc::clone(server)),
1283        };
1284        let file = File::from_dyn(buffer.file()).and_then(File::as_local);
1285        if let (Some(file), Some(language_server)) = (file, language_server) {
1286            let lsp_params = request.to_lsp(&file.abs_path(cx), buffer, &language_server, cx);
1287            let status = request.status();
1288            return cx.spawn(move |this, cx| async move {
1289                if !request.check_capabilities(language_server.adapter_server_capabilities()) {
1290                    return Ok(Default::default());
1291                }
1292
1293                let lsp_request = language_server.request::<R::LspRequest>(lsp_params);
1294
1295                let id = lsp_request.id();
1296                let _cleanup = if status.is_some() {
1297                    cx.update(|cx| {
1298                        this.update(cx, |this, cx| {
1299                            this.on_lsp_work_start(
1300                                language_server.server_id(),
1301                                id.to_string(),
1302                                LanguageServerProgress {
1303                                    is_disk_based_diagnostics_progress: false,
1304                                    is_cancellable: false,
1305                                    title: None,
1306                                    message: status.clone(),
1307                                    percentage: None,
1308                                    last_update_at: cx.background_executor().now(),
1309                                },
1310                                cx,
1311                            );
1312                        })
1313                    })
1314                    .log_err();
1315
1316                    Some(defer(|| {
1317                        cx.update(|cx| {
1318                            this.update(cx, |this, cx| {
1319                                this.on_lsp_work_end(
1320                                    language_server.server_id(),
1321                                    id.to_string(),
1322                                    cx,
1323                                );
1324                            })
1325                        })
1326                        .log_err();
1327                    }))
1328                } else {
1329                    None
1330                };
1331
1332                let result = lsp_request.await;
1333
1334                let response = result.map_err(|err| {
1335                    log::warn!(
1336                        "Generic lsp request to {} failed: {}",
1337                        language_server.name(),
1338                        err
1339                    );
1340                    err
1341                })?;
1342
1343                request
1344                    .response_from_lsp(
1345                        response,
1346                        this.upgrade().ok_or_else(|| anyhow!("no app context"))?,
1347                        buffer_handle,
1348                        language_server.server_id(),
1349                        cx.clone(),
1350                    )
1351                    .await
1352            });
1353        }
1354
1355        Task::ready(Ok(Default::default()))
1356    }
1357
1358    fn on_settings_changed(&mut self, cx: &mut ModelContext<Self>) {
1359        let mut language_servers_to_start = Vec::new();
1360        let mut language_formatters_to_check = Vec::new();
1361        for buffer in self.buffer_store.read(cx).buffers() {
1362            let buffer = buffer.read(cx);
1363            let buffer_file = File::from_dyn(buffer.file());
1364            let buffer_language = buffer.language();
1365            let settings = language_settings(buffer_language, buffer.file(), cx);
1366            if let Some(language) = buffer_language {
1367                if settings.enable_language_server {
1368                    if let Some(file) = buffer_file {
1369                        language_servers_to_start.push((file.worktree.clone(), language.name()));
1370                    }
1371                }
1372                language_formatters_to_check
1373                    .push((buffer_file.map(|f| f.worktree_id(cx)), settings.clone()));
1374            }
1375        }
1376
1377        let mut language_servers_to_stop = Vec::new();
1378        let mut language_servers_to_restart = Vec::new();
1379        let languages = self.languages.to_vec();
1380
1381        let new_lsp_settings = ProjectSettings::get_global(cx).lsp.clone();
1382        let Some(current_lsp_settings) = self.swap_current_lsp_settings(new_lsp_settings.clone())
1383        else {
1384            return;
1385        };
1386        for (worktree_id, started_lsp_name) in self.started_language_servers() {
1387            let language = languages.iter().find_map(|l| {
1388                let adapter = self
1389                    .languages
1390                    .lsp_adapters(&l.name())
1391                    .iter()
1392                    .find(|adapter| adapter.name == started_lsp_name)?
1393                    .clone();
1394                Some((l, adapter))
1395            });
1396            if let Some((language, adapter)) = language {
1397                let worktree = self.worktree_for_id(worktree_id, cx).ok();
1398                let file = worktree.as_ref().and_then(|tree| {
1399                    tree.update(cx, |tree, cx| tree.root_file(cx).map(|f| f as _))
1400                });
1401                if !language_settings(Some(language), file.as_ref(), cx).enable_language_server {
1402                    language_servers_to_stop.push((worktree_id, started_lsp_name.clone()));
1403                } else if let Some(worktree) = worktree {
1404                    let server_name = &adapter.name;
1405                    match (
1406                        current_lsp_settings.get(server_name),
1407                        new_lsp_settings.get(server_name),
1408                    ) {
1409                        (None, None) => {}
1410                        (Some(_), None) | (None, Some(_)) => {
1411                            language_servers_to_restart.push((worktree, language.name()));
1412                        }
1413                        (Some(current_lsp_settings), Some(new_lsp_settings)) => {
1414                            if current_lsp_settings != new_lsp_settings {
1415                                language_servers_to_restart.push((worktree, language.name()));
1416                            }
1417                        }
1418                    }
1419                }
1420            }
1421        }
1422
1423        for (worktree_id, adapter_name) in language_servers_to_stop {
1424            self.stop_local_language_server(worktree_id, adapter_name, cx)
1425                .detach();
1426        }
1427
1428        if let Some(prettier_store) = self.as_local().map(|s| s.prettier_store.clone()) {
1429            prettier_store.update(cx, |prettier_store, cx| {
1430                prettier_store.on_settings_changed(language_formatters_to_check, cx)
1431            })
1432        }
1433
1434        // Start all the newly-enabled language servers.
1435        for (worktree, language) in language_servers_to_start {
1436            self.start_language_servers(&worktree, language, cx);
1437        }
1438
1439        // Restart all language servers with changed initialization options.
1440        for (worktree, language) in language_servers_to_restart {
1441            self.restart_local_language_servers(worktree, language, cx);
1442        }
1443
1444        cx.notify();
1445    }
1446
1447    pub async fn execute_code_actions_on_servers(
1448        this: &WeakModel<LspStore>,
1449        adapters_and_servers: &[(Arc<CachedLspAdapter>, Arc<LanguageServer>)],
1450        code_actions: Vec<lsp::CodeActionKind>,
1451        buffer: &Model<Buffer>,
1452        push_to_history: bool,
1453        project_transaction: &mut ProjectTransaction,
1454        cx: &mut AsyncAppContext,
1455    ) -> Result<(), anyhow::Error> {
1456        for (lsp_adapter, language_server) in adapters_and_servers.iter() {
1457            let code_actions = code_actions.clone();
1458
1459            let actions = this
1460                .update(cx, move |this, cx| {
1461                    let request = GetCodeActions {
1462                        range: text::Anchor::MIN..text::Anchor::MAX,
1463                        kinds: Some(code_actions),
1464                    };
1465                    let server = LanguageServerToQuery::Other(language_server.server_id());
1466                    this.request_lsp(buffer.clone(), server, request, cx)
1467                })?
1468                .await?;
1469
1470            for mut action in actions {
1471                Self::try_resolve_code_action(language_server, &mut action)
1472                    .await
1473                    .context("resolving a formatting code action")?;
1474
1475                if let Some(edit) = action.lsp_action.edit {
1476                    if edit.changes.is_none() && edit.document_changes.is_none() {
1477                        continue;
1478                    }
1479
1480                    let new = Self::deserialize_workspace_edit(
1481                        this.upgrade().ok_or_else(|| anyhow!("project dropped"))?,
1482                        edit,
1483                        push_to_history,
1484                        lsp_adapter.clone(),
1485                        language_server.clone(),
1486                        cx,
1487                    )
1488                    .await?;
1489                    project_transaction.0.extend(new.0);
1490                }
1491
1492                if let Some(command) = action.lsp_action.command {
1493                    this.update(cx, |this, _| {
1494                        if let LspStoreMode::Local(mode) = &mut this.mode {
1495                            mode.last_workspace_edits_by_language_server
1496                                .remove(&language_server.server_id());
1497                        }
1498                    })?;
1499
1500                    language_server
1501                        .request::<lsp::request::ExecuteCommand>(lsp::ExecuteCommandParams {
1502                            command: command.command,
1503                            arguments: command.arguments.unwrap_or_default(),
1504                            ..Default::default()
1505                        })
1506                        .await?;
1507
1508                    this.update(cx, |this, _| {
1509                        if let LspStoreMode::Local(mode) = &mut this.mode {
1510                            project_transaction.0.extend(
1511                                mode.last_workspace_edits_by_language_server
1512                                    .remove(&language_server.server_id())
1513                                    .unwrap_or_default()
1514                                    .0,
1515                            )
1516                        }
1517                    })?;
1518                }
1519            }
1520        }
1521
1522        Ok(())
1523    }
1524
1525    async fn try_resolve_code_action(
1526        lang_server: &LanguageServer,
1527        action: &mut CodeAction,
1528    ) -> anyhow::Result<()> {
1529        if GetCodeActions::can_resolve_actions(&lang_server.capabilities())
1530            && action.lsp_action.data.is_some()
1531            && (action.lsp_action.command.is_none() || action.lsp_action.edit.is_none())
1532        {
1533            action.lsp_action = lang_server
1534                .request::<lsp::request::CodeActionResolveRequest>(action.lsp_action.clone())
1535                .await?;
1536        }
1537
1538        anyhow::Ok(())
1539    }
1540
1541    pub fn apply_code_action(
1542        &self,
1543        buffer_handle: Model<Buffer>,
1544        mut action: CodeAction,
1545        push_to_history: bool,
1546        cx: &mut ModelContext<Self>,
1547    ) -> Task<Result<ProjectTransaction>> {
1548        if let Some((upstream_client, project_id)) = self.upstream_client() {
1549            let request = proto::ApplyCodeAction {
1550                project_id,
1551                buffer_id: buffer_handle.read(cx).remote_id().into(),
1552                action: Some(Self::serialize_code_action(&action)),
1553            };
1554            let buffer_store = self.buffer_store();
1555            cx.spawn(move |_, mut cx| async move {
1556                let response = upstream_client
1557                    .request(request)
1558                    .await?
1559                    .transaction
1560                    .ok_or_else(|| anyhow!("missing transaction"))?;
1561
1562                buffer_store
1563                    .update(&mut cx, |buffer_store, cx| {
1564                        buffer_store.deserialize_project_transaction(response, push_to_history, cx)
1565                    })?
1566                    .await
1567            })
1568        } else {
1569            let buffer = buffer_handle.read(cx);
1570            let (lsp_adapter, lang_server) = if let Some((adapter, server)) =
1571                self.language_server_for_buffer(buffer, action.server_id, cx)
1572            {
1573                (adapter.clone(), server.clone())
1574            } else {
1575                return Task::ready(Ok(Default::default()));
1576            };
1577            cx.spawn(move |this, mut cx| async move {
1578                Self::try_resolve_code_action(&lang_server, &mut action)
1579                    .await
1580                    .context("resolving a code action")?;
1581                if let Some(edit) = action.lsp_action.edit {
1582                    if edit.changes.is_some() || edit.document_changes.is_some() {
1583                        return Self::deserialize_workspace_edit(
1584                            this.upgrade().ok_or_else(|| anyhow!("no app present"))?,
1585                            edit,
1586                            push_to_history,
1587                            lsp_adapter.clone(),
1588                            lang_server.clone(),
1589                            &mut cx,
1590                        )
1591                        .await;
1592                    }
1593                }
1594
1595                if let Some(command) = action.lsp_action.command {
1596                    this.update(&mut cx, |this, _| {
1597                        this.as_local_mut()
1598                            .unwrap()
1599                            .last_workspace_edits_by_language_server
1600                            .remove(&lang_server.server_id());
1601                    })?;
1602
1603                    let result = lang_server
1604                        .request::<lsp::request::ExecuteCommand>(lsp::ExecuteCommandParams {
1605                            command: command.command,
1606                            arguments: command.arguments.unwrap_or_default(),
1607                            ..Default::default()
1608                        })
1609                        .await;
1610
1611                    result?;
1612
1613                    return this.update(&mut cx, |this, _| {
1614                        this.as_local_mut()
1615                            .unwrap()
1616                            .last_workspace_edits_by_language_server
1617                            .remove(&lang_server.server_id())
1618                            .unwrap_or_default()
1619                    });
1620                }
1621
1622                Ok(ProjectTransaction::default())
1623            })
1624        }
1625    }
1626
1627    pub fn resolve_inlay_hint(
1628        &self,
1629        hint: InlayHint,
1630        buffer_handle: Model<Buffer>,
1631        server_id: LanguageServerId,
1632        cx: &mut ModelContext<Self>,
1633    ) -> Task<anyhow::Result<InlayHint>> {
1634        if let Some((upstream_client, project_id)) = self.upstream_client() {
1635            let request = proto::ResolveInlayHint {
1636                project_id,
1637                buffer_id: buffer_handle.read(cx).remote_id().into(),
1638                language_server_id: server_id.0 as u64,
1639                hint: Some(InlayHints::project_to_proto_hint(hint.clone())),
1640            };
1641            cx.spawn(move |_, _| async move {
1642                let response = upstream_client
1643                    .request(request)
1644                    .await
1645                    .context("inlay hints proto request")?;
1646                match response.hint {
1647                    Some(resolved_hint) => InlayHints::proto_to_project_hint(resolved_hint)
1648                        .context("inlay hints proto resolve response conversion"),
1649                    None => Ok(hint),
1650                }
1651            })
1652        } else {
1653            let buffer = buffer_handle.read(cx);
1654            let (_, lang_server) = if let Some((adapter, server)) =
1655                self.language_server_for_buffer(buffer, server_id, cx)
1656            {
1657                (adapter.clone(), server.clone())
1658            } else {
1659                return Task::ready(Ok(hint));
1660            };
1661            if !InlayHints::can_resolve_inlays(&lang_server.capabilities()) {
1662                return Task::ready(Ok(hint));
1663            }
1664
1665            let buffer_snapshot = buffer.snapshot();
1666            cx.spawn(move |_, mut cx| async move {
1667                let resolve_task = lang_server.request::<lsp::request::InlayHintResolveRequest>(
1668                    InlayHints::project_to_lsp_hint(hint, &buffer_snapshot),
1669                );
1670                let resolved_hint = resolve_task
1671                    .await
1672                    .context("inlay hint resolve LSP request")?;
1673                let resolved_hint = InlayHints::lsp_to_project_hint(
1674                    resolved_hint,
1675                    &buffer_handle,
1676                    server_id,
1677                    ResolveState::Resolved,
1678                    false,
1679                    &mut cx,
1680                )
1681                .await?;
1682                Ok(resolved_hint)
1683            })
1684        }
1685    }
1686
1687    pub(crate) fn linked_edit(
1688        &self,
1689        buffer: &Model<Buffer>,
1690        position: Anchor,
1691        cx: &mut ModelContext<Self>,
1692    ) -> Task<Result<Vec<Range<Anchor>>>> {
1693        let snapshot = buffer.read(cx).snapshot();
1694        let scope = snapshot.language_scope_at(position);
1695        let Some(server_id) = self
1696            .language_servers_for_buffer(buffer.read(cx), cx)
1697            .filter(|(_, server)| {
1698                server
1699                    .capabilities()
1700                    .linked_editing_range_provider
1701                    .is_some()
1702            })
1703            .filter(|(adapter, _)| {
1704                scope
1705                    .as_ref()
1706                    .map(|scope| scope.language_allowed(&adapter.name))
1707                    .unwrap_or(true)
1708            })
1709            .map(|(_, server)| LanguageServerToQuery::Other(server.server_id()))
1710            .next()
1711            .or_else(|| {
1712                self.upstream_client()
1713                    .is_some()
1714                    .then_some(LanguageServerToQuery::Primary)
1715            })
1716            .filter(|_| {
1717                maybe!({
1718                    let language_name = buffer.read(cx).language_at(position)?.name();
1719                    Some(
1720                        AllLanguageSettings::get_global(cx)
1721                            .language(Some(&language_name))
1722                            .linked_edits,
1723                    )
1724                }) == Some(true)
1725            })
1726        else {
1727            return Task::ready(Ok(vec![]));
1728        };
1729
1730        self.request_lsp(
1731            buffer.clone(),
1732            server_id,
1733            LinkedEditingRange { position },
1734            cx,
1735        )
1736    }
1737
1738    fn apply_on_type_formatting(
1739        &mut self,
1740        buffer: Model<Buffer>,
1741        position: Anchor,
1742        trigger: String,
1743        cx: &mut ModelContext<Self>,
1744    ) -> Task<Result<Option<Transaction>>> {
1745        if let Some((client, project_id)) = self.upstream_client() {
1746            let request = proto::OnTypeFormatting {
1747                project_id,
1748                buffer_id: buffer.read(cx).remote_id().into(),
1749                position: Some(serialize_anchor(&position)),
1750                trigger,
1751                version: serialize_version(&buffer.read(cx).version()),
1752            };
1753            cx.spawn(move |_, _| async move {
1754                client
1755                    .request(request)
1756                    .await?
1757                    .transaction
1758                    .map(language::proto::deserialize_transaction)
1759                    .transpose()
1760            })
1761        } else if let Some(local) = self.as_local_mut() {
1762            let buffer_id = buffer.read(cx).remote_id();
1763            local.buffers_being_formatted.insert(buffer_id);
1764            cx.spawn(move |this, mut cx| async move {
1765                let _cleanup = defer({
1766                    let this = this.clone();
1767                    let mut cx = cx.clone();
1768                    move || {
1769                        this.update(&mut cx, |this, _| {
1770                            if let Some(local) = this.as_local_mut() {
1771                                local.buffers_being_formatted.remove(&buffer_id);
1772                            }
1773                        })
1774                        .ok();
1775                    }
1776                });
1777
1778                buffer
1779                    .update(&mut cx, |buffer, _| {
1780                        buffer.wait_for_edits(Some(position.timestamp))
1781                    })?
1782                    .await?;
1783                this.update(&mut cx, |this, cx| {
1784                    let position = position.to_point_utf16(buffer.read(cx));
1785                    this.on_type_format(buffer, position, trigger, false, cx)
1786                })?
1787                .await
1788            })
1789        } else {
1790            Task::ready(Err(anyhow!("No upstream client or local language server")))
1791        }
1792    }
1793
1794    pub fn on_type_format<T: ToPointUtf16>(
1795        &mut self,
1796        buffer: Model<Buffer>,
1797        position: T,
1798        trigger: String,
1799        push_to_history: bool,
1800        cx: &mut ModelContext<Self>,
1801    ) -> Task<Result<Option<Transaction>>> {
1802        let position = position.to_point_utf16(buffer.read(cx));
1803        self.on_type_format_impl(buffer, position, trigger, push_to_history, cx)
1804    }
1805
1806    fn on_type_format_impl(
1807        &mut self,
1808        buffer: Model<Buffer>,
1809        position: PointUtf16,
1810        trigger: String,
1811        push_to_history: bool,
1812        cx: &mut ModelContext<Self>,
1813    ) -> Task<Result<Option<Transaction>>> {
1814        let options = buffer.update(cx, |buffer, cx| {
1815            lsp_command::lsp_formatting_options(language_settings(
1816                buffer.language_at(position).as_ref(),
1817                buffer.file(),
1818                cx,
1819            ))
1820        });
1821        self.request_lsp(
1822            buffer.clone(),
1823            LanguageServerToQuery::Primary,
1824            OnTypeFormatting {
1825                position,
1826                trigger,
1827                options,
1828                push_to_history,
1829            },
1830            cx,
1831        )
1832    }
1833
1834    pub async fn format_via_lsp(
1835        this: &WeakModel<Self>,
1836        buffer: &Model<Buffer>,
1837        abs_path: &Path,
1838        language_server: &Arc<LanguageServer>,
1839        settings: &LanguageSettings,
1840        cx: &mut AsyncAppContext,
1841    ) -> Result<Vec<(Range<Anchor>, String)>> {
1842        let uri = lsp::Url::from_file_path(abs_path)
1843            .map_err(|_| anyhow!("failed to convert abs path to uri"))?;
1844        let text_document = lsp::TextDocumentIdentifier::new(uri);
1845        let capabilities = &language_server.capabilities();
1846
1847        let formatting_provider = capabilities.document_formatting_provider.as_ref();
1848        let range_formatting_provider = capabilities.document_range_formatting_provider.as_ref();
1849
1850        let lsp_edits = if matches!(formatting_provider, Some(p) if *p != OneOf::Left(false)) {
1851            language_server
1852                .request::<lsp::request::Formatting>(lsp::DocumentFormattingParams {
1853                    text_document,
1854                    options: lsp_command::lsp_formatting_options(settings),
1855                    work_done_progress_params: Default::default(),
1856                })
1857                .await?
1858        } else if matches!(range_formatting_provider, Some(p) if *p != OneOf::Left(false)) {
1859            let buffer_start = lsp::Position::new(0, 0);
1860            let buffer_end = buffer.update(cx, |b, _| point_to_lsp(b.max_point_utf16()))?;
1861
1862            language_server
1863                .request::<lsp::request::RangeFormatting>(lsp::DocumentRangeFormattingParams {
1864                    text_document,
1865                    range: lsp::Range::new(buffer_start, buffer_end),
1866                    options: lsp_command::lsp_formatting_options(settings),
1867                    work_done_progress_params: Default::default(),
1868                })
1869                .await?
1870        } else {
1871            None
1872        };
1873
1874        if let Some(lsp_edits) = lsp_edits {
1875            this.update(cx, |this, cx| {
1876                this.edits_from_lsp(buffer, lsp_edits, language_server.server_id(), None, cx)
1877            })?
1878            .await
1879        } else {
1880            Ok(Vec::new())
1881        }
1882    }
1883
1884    pub fn code_actions(
1885        &mut self,
1886        buffer_handle: &Model<Buffer>,
1887        range: Range<Anchor>,
1888        cx: &mut ModelContext<Self>,
1889    ) -> Task<Result<Vec<CodeAction>>> {
1890        if let Some((upstream_client, project_id)) = self.upstream_client() {
1891            let request_task = upstream_client.request(proto::MultiLspQuery {
1892                buffer_id: buffer_handle.read(cx).remote_id().into(),
1893                version: serialize_version(&buffer_handle.read(cx).version()),
1894                project_id,
1895                strategy: Some(proto::multi_lsp_query::Strategy::All(
1896                    proto::AllLanguageServers {},
1897                )),
1898                request: Some(proto::multi_lsp_query::Request::GetCodeActions(
1899                    GetCodeActions {
1900                        range: range.clone(),
1901                        kinds: None,
1902                    }
1903                    .to_proto(project_id, buffer_handle.read(cx)),
1904                )),
1905            });
1906            let buffer = buffer_handle.clone();
1907            cx.spawn(|weak_project, cx| async move {
1908                let Some(project) = weak_project.upgrade() else {
1909                    return Ok(Vec::new());
1910                };
1911                let responses = request_task.await?.responses;
1912                let actions = join_all(
1913                    responses
1914                        .into_iter()
1915                        .filter_map(|lsp_response| match lsp_response.response? {
1916                            proto::lsp_response::Response::GetCodeActionsResponse(response) => {
1917                                Some(response)
1918                            }
1919                            unexpected => {
1920                                debug_panic!("Unexpected response: {unexpected:?}");
1921                                None
1922                            }
1923                        })
1924                        .map(|code_actions_response| {
1925                            GetCodeActions {
1926                                range: range.clone(),
1927                                kinds: None,
1928                            }
1929                            .response_from_proto(
1930                                code_actions_response,
1931                                project.clone(),
1932                                buffer.clone(),
1933                                cx.clone(),
1934                            )
1935                        }),
1936                )
1937                .await;
1938
1939                Ok(actions
1940                    .into_iter()
1941                    .collect::<Result<Vec<Vec<_>>>>()?
1942                    .into_iter()
1943                    .flatten()
1944                    .collect())
1945            })
1946        } else {
1947            let all_actions_task = self.request_multiple_lsp_locally(
1948                buffer_handle,
1949                Some(range.start),
1950                GetCodeActions {
1951                    range: range.clone(),
1952                    kinds: None,
1953                },
1954                cx,
1955            );
1956            cx.spawn(
1957                |_, _| async move { Ok(all_actions_task.await.into_iter().flatten().collect()) },
1958            )
1959        }
1960    }
1961
1962    #[inline(never)]
1963    pub fn completions(
1964        &self,
1965        buffer: &Model<Buffer>,
1966        position: PointUtf16,
1967        context: CompletionContext,
1968        cx: &mut ModelContext<Self>,
1969    ) -> Task<Result<Vec<Completion>>> {
1970        let language_registry = self.languages.clone();
1971
1972        if let Some((upstream_client, project_id)) = self.upstream_client() {
1973            let task = self.send_lsp_proto_request(
1974                buffer.clone(),
1975                upstream_client,
1976                project_id,
1977                GetCompletions { position, context },
1978                cx,
1979            );
1980            let language = buffer.read(cx).language().cloned();
1981
1982            // In the future, we should provide project guests with the names of LSP adapters,
1983            // so that they can use the correct LSP adapter when computing labels. For now,
1984            // guests just use the first LSP adapter associated with the buffer's language.
1985            let lsp_adapter = language.as_ref().and_then(|language| {
1986                language_registry
1987                    .lsp_adapters(&language.name())
1988                    .first()
1989                    .cloned()
1990            });
1991
1992            cx.foreground_executor().spawn(async move {
1993                let completions = task.await?;
1994                let mut result = Vec::new();
1995                populate_labels_for_completions(
1996                    completions,
1997                    &language_registry,
1998                    language,
1999                    lsp_adapter,
2000                    &mut result,
2001                )
2002                .await;
2003                Ok(result)
2004            })
2005        } else {
2006            let snapshot = buffer.read(cx).snapshot();
2007            let offset = position.to_offset(&snapshot);
2008            let scope = snapshot.language_scope_at(offset);
2009            let language = snapshot.language().cloned();
2010
2011            let server_ids: Vec<_> = self
2012                .language_servers_for_buffer(buffer.read(cx), cx)
2013                .filter(|(_, server)| server.capabilities().completion_provider.is_some())
2014                .filter(|(adapter, _)| {
2015                    scope
2016                        .as_ref()
2017                        .map(|scope| scope.language_allowed(&adapter.name))
2018                        .unwrap_or(true)
2019                })
2020                .map(|(_, server)| server.server_id())
2021                .collect();
2022
2023            let buffer = buffer.clone();
2024            cx.spawn(move |this, mut cx| async move {
2025                let mut tasks = Vec::with_capacity(server_ids.len());
2026                this.update(&mut cx, |this, cx| {
2027                    for server_id in server_ids {
2028                        let lsp_adapter = this.language_server_adapter_for_id(server_id);
2029                        tasks.push((
2030                            lsp_adapter,
2031                            this.request_lsp(
2032                                buffer.clone(),
2033                                LanguageServerToQuery::Other(server_id),
2034                                GetCompletions {
2035                                    position,
2036                                    context: context.clone(),
2037                                },
2038                                cx,
2039                            ),
2040                        ));
2041                    }
2042                })?;
2043
2044                let mut completions = Vec::new();
2045                for (lsp_adapter, task) in tasks {
2046                    if let Ok(new_completions) = task.await {
2047                        populate_labels_for_completions(
2048                            new_completions,
2049                            &language_registry,
2050                            language.clone(),
2051                            lsp_adapter,
2052                            &mut completions,
2053                        )
2054                        .await;
2055                    }
2056                }
2057
2058                Ok(completions)
2059            })
2060        }
2061    }
2062
2063    pub fn resolve_completions(
2064        &self,
2065        buffer: Model<Buffer>,
2066        completion_indices: Vec<usize>,
2067        completions: Arc<RwLock<Box<[Completion]>>>,
2068        cx: &mut ModelContext<Self>,
2069    ) -> Task<Result<bool>> {
2070        let client = self.upstream_client();
2071        let language_registry = self.languages.clone();
2072
2073        let buffer_id = buffer.read(cx).remote_id();
2074        let buffer_snapshot = buffer.read(cx).snapshot();
2075
2076        cx.spawn(move |this, cx| async move {
2077            let mut did_resolve = false;
2078            if let Some((client, project_id)) = client {
2079                for completion_index in completion_indices {
2080                    let (server_id, completion) = {
2081                        let completions_guard = completions.read();
2082                        let completion = &completions_guard[completion_index];
2083                        did_resolve = true;
2084                        let server_id = completion.server_id;
2085                        let completion = completion.lsp_completion.clone();
2086
2087                        (server_id, completion)
2088                    };
2089
2090                    Self::resolve_completion_remote(
2091                        project_id,
2092                        server_id,
2093                        buffer_id,
2094                        completions.clone(),
2095                        completion_index,
2096                        completion,
2097                        client.clone(),
2098                        language_registry.clone(),
2099                    )
2100                    .await;
2101                }
2102            } else {
2103                for completion_index in completion_indices {
2104                    let (server_id, completion) = {
2105                        let completions_guard = completions.read();
2106                        let completion = &completions_guard[completion_index];
2107                        let server_id = completion.server_id;
2108                        let completion = completion.lsp_completion.clone();
2109
2110                        (server_id, completion)
2111                    };
2112
2113                    let server = this
2114                        .read_with(&cx, |this, _| this.language_server_for_id(server_id))
2115                        .ok()
2116                        .flatten();
2117                    let Some(server) = server else {
2118                        continue;
2119                    };
2120
2121                    did_resolve = true;
2122                    Self::resolve_completion_local(
2123                        server,
2124                        &buffer_snapshot,
2125                        completions.clone(),
2126                        completion_index,
2127                        completion,
2128                        language_registry.clone(),
2129                    )
2130                    .await;
2131                }
2132            }
2133
2134            Ok(did_resolve)
2135        })
2136    }
2137
2138    async fn resolve_completion_local(
2139        server: Arc<lsp::LanguageServer>,
2140        snapshot: &BufferSnapshot,
2141        completions: Arc<RwLock<Box<[Completion]>>>,
2142        completion_index: usize,
2143        completion: lsp::CompletionItem,
2144        language_registry: Arc<LanguageRegistry>,
2145    ) {
2146        let can_resolve = server
2147            .capabilities()
2148            .completion_provider
2149            .as_ref()
2150            .and_then(|options| options.resolve_provider)
2151            .unwrap_or(false);
2152        if !can_resolve {
2153            return;
2154        }
2155
2156        let request = server.request::<lsp::request::ResolveCompletionItem>(completion);
2157        let Some(completion_item) = request.await.log_err() else {
2158            return;
2159        };
2160
2161        if let Some(lsp_documentation) = completion_item.documentation.as_ref() {
2162            let documentation = language::prepare_completion_documentation(
2163                lsp_documentation,
2164                &language_registry,
2165                None, // TODO: Try to reasonably work out which language the completion is for
2166            )
2167            .await;
2168
2169            let mut completions = completions.write();
2170            let completion = &mut completions[completion_index];
2171            completion.documentation = Some(documentation);
2172        } else {
2173            let mut completions = completions.write();
2174            let completion = &mut completions[completion_index];
2175            completion.documentation = Some(Documentation::Undocumented);
2176        }
2177
2178        if let Some(text_edit) = completion_item.text_edit.as_ref() {
2179            // Technically we don't have to parse the whole `text_edit`, since the only
2180            // language server we currently use that does update `text_edit` in `completionItem/resolve`
2181            // is `typescript-language-server` and they only update `text_edit.new_text`.
2182            // But we should not rely on that.
2183            let edit = parse_completion_text_edit(text_edit, snapshot);
2184
2185            if let Some((old_range, mut new_text)) = edit {
2186                LineEnding::normalize(&mut new_text);
2187
2188                let mut completions = completions.write();
2189                let completion = &mut completions[completion_index];
2190
2191                completion.new_text = new_text;
2192                completion.old_range = old_range;
2193            }
2194        }
2195        if completion_item.insert_text_format == Some(InsertTextFormat::SNIPPET) {
2196            // vtsls might change the type of completion after resolution.
2197            let mut completions = completions.write();
2198            let completion = &mut completions[completion_index];
2199            if completion_item.insert_text_format != completion.lsp_completion.insert_text_format {
2200                completion.lsp_completion.insert_text_format = completion_item.insert_text_format;
2201            }
2202        }
2203
2204        let mut completions = completions.write();
2205        let completion = &mut completions[completion_index];
2206        completion.lsp_completion = completion_item;
2207    }
2208
2209    #[allow(clippy::too_many_arguments)]
2210    async fn resolve_completion_remote(
2211        project_id: u64,
2212        server_id: LanguageServerId,
2213        buffer_id: BufferId,
2214        completions: Arc<RwLock<Box<[Completion]>>>,
2215        completion_index: usize,
2216        completion: lsp::CompletionItem,
2217        client: AnyProtoClient,
2218        language_registry: Arc<LanguageRegistry>,
2219    ) {
2220        let request = proto::ResolveCompletionDocumentation {
2221            project_id,
2222            language_server_id: server_id.0 as u64,
2223            lsp_completion: serde_json::to_string(&completion).unwrap().into_bytes(),
2224            buffer_id: buffer_id.into(),
2225        };
2226
2227        let Some(response) = client
2228            .request(request)
2229            .await
2230            .context("completion documentation resolve proto request")
2231            .log_err()
2232        else {
2233            return;
2234        };
2235        let Some(lsp_completion) = serde_json::from_slice(&response.lsp_completion).log_err()
2236        else {
2237            return;
2238        };
2239
2240        let documentation = if response.documentation.is_empty() {
2241            Documentation::Undocumented
2242        } else if response.documentation_is_markdown {
2243            Documentation::MultiLineMarkdown(
2244                markdown::parse_markdown(&response.documentation, &language_registry, None).await,
2245            )
2246        } else if response.documentation.lines().count() <= 1 {
2247            Documentation::SingleLine(response.documentation)
2248        } else {
2249            Documentation::MultiLinePlainText(response.documentation)
2250        };
2251
2252        let mut completions = completions.write();
2253        let completion = &mut completions[completion_index];
2254        completion.documentation = Some(documentation);
2255        completion.lsp_completion = lsp_completion;
2256
2257        let old_range = response
2258            .old_start
2259            .and_then(deserialize_anchor)
2260            .zip(response.old_end.and_then(deserialize_anchor));
2261        if let Some((old_start, old_end)) = old_range {
2262            if !response.new_text.is_empty() {
2263                completion.new_text = response.new_text;
2264                completion.old_range = old_start..old_end;
2265            }
2266        }
2267    }
2268
2269    pub fn apply_additional_edits_for_completion(
2270        &self,
2271        buffer_handle: Model<Buffer>,
2272        completion: Completion,
2273        push_to_history: bool,
2274        cx: &mut ModelContext<Self>,
2275    ) -> Task<Result<Option<Transaction>>> {
2276        let buffer = buffer_handle.read(cx);
2277        let buffer_id = buffer.remote_id();
2278
2279        if let Some((client, project_id)) = self.upstream_client() {
2280            cx.spawn(move |_, mut cx| async move {
2281                let response = client
2282                    .request(proto::ApplyCompletionAdditionalEdits {
2283                        project_id,
2284                        buffer_id: buffer_id.into(),
2285                        completion: Some(Self::serialize_completion(&CoreCompletion {
2286                            old_range: completion.old_range,
2287                            new_text: completion.new_text,
2288                            server_id: completion.server_id,
2289                            lsp_completion: completion.lsp_completion,
2290                        })),
2291                    })
2292                    .await?;
2293
2294                if let Some(transaction) = response.transaction {
2295                    let transaction = language::proto::deserialize_transaction(transaction)?;
2296                    buffer_handle
2297                        .update(&mut cx, |buffer, _| {
2298                            buffer.wait_for_edits(transaction.edit_ids.iter().copied())
2299                        })?
2300                        .await?;
2301                    if push_to_history {
2302                        buffer_handle.update(&mut cx, |buffer, _| {
2303                            buffer.push_transaction(transaction.clone(), Instant::now());
2304                        })?;
2305                    }
2306                    Ok(Some(transaction))
2307                } else {
2308                    Ok(None)
2309                }
2310            })
2311        } else {
2312            let server_id = completion.server_id;
2313            let lang_server = match self.language_server_for_buffer(buffer, server_id, cx) {
2314                Some((_, server)) => server.clone(),
2315                _ => return Task::ready(Ok(Default::default())),
2316            };
2317
2318            cx.spawn(move |this, mut cx| async move {
2319                let can_resolve = lang_server
2320                    .capabilities()
2321                    .completion_provider
2322                    .as_ref()
2323                    .and_then(|options| options.resolve_provider)
2324                    .unwrap_or(false);
2325                let additional_text_edits = if can_resolve {
2326                    lang_server
2327                        .request::<lsp::request::ResolveCompletionItem>(completion.lsp_completion)
2328                        .await?
2329                        .additional_text_edits
2330                } else {
2331                    completion.lsp_completion.additional_text_edits
2332                };
2333                if let Some(edits) = additional_text_edits {
2334                    let edits = this
2335                        .update(&mut cx, |this, cx| {
2336                            this.edits_from_lsp(
2337                                &buffer_handle,
2338                                edits,
2339                                lang_server.server_id(),
2340                                None,
2341                                cx,
2342                            )
2343                        })?
2344                        .await?;
2345
2346                    buffer_handle.update(&mut cx, |buffer, cx| {
2347                        buffer.finalize_last_transaction();
2348                        buffer.start_transaction();
2349
2350                        for (range, text) in edits {
2351                            let primary = &completion.old_range;
2352                            let start_within = primary.start.cmp(&range.start, buffer).is_le()
2353                                && primary.end.cmp(&range.start, buffer).is_ge();
2354                            let end_within = range.start.cmp(&primary.end, buffer).is_le()
2355                                && range.end.cmp(&primary.end, buffer).is_ge();
2356
2357                            //Skip additional edits which overlap with the primary completion edit
2358                            //https://github.com/zed-industries/zed/pull/1871
2359                            if !start_within && !end_within {
2360                                buffer.edit([(range, text)], None, cx);
2361                            }
2362                        }
2363
2364                        let transaction = if buffer.end_transaction(cx).is_some() {
2365                            let transaction = buffer.finalize_last_transaction().unwrap().clone();
2366                            if !push_to_history {
2367                                buffer.forget_transaction(transaction.id);
2368                            }
2369                            Some(transaction)
2370                        } else {
2371                            None
2372                        };
2373                        Ok(transaction)
2374                    })?
2375                } else {
2376                    Ok(None)
2377                }
2378            })
2379        }
2380    }
2381
2382    pub fn inlay_hints(
2383        &mut self,
2384        buffer_handle: Model<Buffer>,
2385        range: Range<Anchor>,
2386        cx: &mut ModelContext<Self>,
2387    ) -> Task<anyhow::Result<Vec<InlayHint>>> {
2388        let buffer = buffer_handle.read(cx);
2389        let range_start = range.start;
2390        let range_end = range.end;
2391        let buffer_id = buffer.remote_id().into();
2392        let lsp_request = InlayHints { range };
2393
2394        if let Some((client, project_id)) = self.upstream_client() {
2395            let request = proto::InlayHints {
2396                project_id,
2397                buffer_id,
2398                start: Some(serialize_anchor(&range_start)),
2399                end: Some(serialize_anchor(&range_end)),
2400                version: serialize_version(&buffer_handle.read(cx).version()),
2401            };
2402            cx.spawn(move |project, cx| async move {
2403                let response = client
2404                    .request(request)
2405                    .await
2406                    .context("inlay hints proto request")?;
2407                LspCommand::response_from_proto(
2408                    lsp_request,
2409                    response,
2410                    project.upgrade().ok_or_else(|| anyhow!("No project"))?,
2411                    buffer_handle.clone(),
2412                    cx.clone(),
2413                )
2414                .await
2415                .context("inlay hints proto response conversion")
2416            })
2417        } else {
2418            let lsp_request_task = self.request_lsp(
2419                buffer_handle.clone(),
2420                LanguageServerToQuery::Primary,
2421                lsp_request,
2422                cx,
2423            );
2424            cx.spawn(move |_, mut cx| async move {
2425                buffer_handle
2426                    .update(&mut cx, |buffer, _| {
2427                        buffer.wait_for_edits(vec![range_start.timestamp, range_end.timestamp])
2428                    })?
2429                    .await
2430                    .context("waiting for inlay hint request range edits")?;
2431                lsp_request_task.await.context("inlay hints LSP request")
2432            })
2433        }
2434    }
2435
2436    pub fn signature_help<T: ToPointUtf16>(
2437        &self,
2438        buffer: &Model<Buffer>,
2439        position: T,
2440        cx: &mut ModelContext<Self>,
2441    ) -> Task<Vec<SignatureHelp>> {
2442        let position = position.to_point_utf16(buffer.read(cx));
2443
2444        if let Some((client, upstream_project_id)) = self.upstream_client() {
2445            let request_task = client.request(proto::MultiLspQuery {
2446                buffer_id: buffer.read(cx).remote_id().into(),
2447                version: serialize_version(&buffer.read(cx).version()),
2448                project_id: upstream_project_id,
2449                strategy: Some(proto::multi_lsp_query::Strategy::All(
2450                    proto::AllLanguageServers {},
2451                )),
2452                request: Some(proto::multi_lsp_query::Request::GetSignatureHelp(
2453                    GetSignatureHelp { position }.to_proto(upstream_project_id, buffer.read(cx)),
2454                )),
2455            });
2456            let buffer = buffer.clone();
2457            cx.spawn(|weak_project, cx| async move {
2458                let Some(project) = weak_project.upgrade() else {
2459                    return Vec::new();
2460                };
2461                join_all(
2462                    request_task
2463                        .await
2464                        .log_err()
2465                        .map(|response| response.responses)
2466                        .unwrap_or_default()
2467                        .into_iter()
2468                        .filter_map(|lsp_response| match lsp_response.response? {
2469                            proto::lsp_response::Response::GetSignatureHelpResponse(response) => {
2470                                Some(response)
2471                            }
2472                            unexpected => {
2473                                debug_panic!("Unexpected response: {unexpected:?}");
2474                                None
2475                            }
2476                        })
2477                        .map(|signature_response| {
2478                            let response = GetSignatureHelp { position }.response_from_proto(
2479                                signature_response,
2480                                project.clone(),
2481                                buffer.clone(),
2482                                cx.clone(),
2483                            );
2484                            async move { response.await.log_err().flatten() }
2485                        }),
2486                )
2487                .await
2488                .into_iter()
2489                .flatten()
2490                .collect()
2491            })
2492        } else {
2493            let all_actions_task = self.request_multiple_lsp_locally(
2494                buffer,
2495                Some(position),
2496                GetSignatureHelp { position },
2497                cx,
2498            );
2499            cx.spawn(|_, _| async move {
2500                all_actions_task
2501                    .await
2502                    .into_iter()
2503                    .flatten()
2504                    .filter(|help| !help.markdown.is_empty())
2505                    .collect::<Vec<_>>()
2506            })
2507        }
2508    }
2509
2510    pub fn hover(
2511        &self,
2512        buffer: &Model<Buffer>,
2513        position: PointUtf16,
2514        cx: &mut ModelContext<Self>,
2515    ) -> Task<Vec<Hover>> {
2516        if let Some((client, upstream_project_id)) = self.upstream_client() {
2517            let request_task = client.request(proto::MultiLspQuery {
2518                buffer_id: buffer.read(cx).remote_id().into(),
2519                version: serialize_version(&buffer.read(cx).version()),
2520                project_id: upstream_project_id,
2521                strategy: Some(proto::multi_lsp_query::Strategy::All(
2522                    proto::AllLanguageServers {},
2523                )),
2524                request: Some(proto::multi_lsp_query::Request::GetHover(
2525                    GetHover { position }.to_proto(upstream_project_id, buffer.read(cx)),
2526                )),
2527            });
2528            let buffer = buffer.clone();
2529            cx.spawn(|weak_project, cx| async move {
2530                let Some(project) = weak_project.upgrade() else {
2531                    return Vec::new();
2532                };
2533                join_all(
2534                    request_task
2535                        .await
2536                        .log_err()
2537                        .map(|response| response.responses)
2538                        .unwrap_or_default()
2539                        .into_iter()
2540                        .filter_map(|lsp_response| match lsp_response.response? {
2541                            proto::lsp_response::Response::GetHoverResponse(response) => {
2542                                Some(response)
2543                            }
2544                            unexpected => {
2545                                debug_panic!("Unexpected response: {unexpected:?}");
2546                                None
2547                            }
2548                        })
2549                        .map(|hover_response| {
2550                            let response = GetHover { position }.response_from_proto(
2551                                hover_response,
2552                                project.clone(),
2553                                buffer.clone(),
2554                                cx.clone(),
2555                            );
2556                            async move {
2557                                response
2558                                    .await
2559                                    .log_err()
2560                                    .flatten()
2561                                    .and_then(remove_empty_hover_blocks)
2562                            }
2563                        }),
2564                )
2565                .await
2566                .into_iter()
2567                .flatten()
2568                .collect()
2569            })
2570        } else {
2571            let all_actions_task = self.request_multiple_lsp_locally(
2572                buffer,
2573                Some(position),
2574                GetHover { position },
2575                cx,
2576            );
2577            cx.spawn(|_, _| async move {
2578                all_actions_task
2579                    .await
2580                    .into_iter()
2581                    .filter_map(|hover| remove_empty_hover_blocks(hover?))
2582                    .collect::<Vec<Hover>>()
2583            })
2584        }
2585    }
2586
2587    pub fn symbols(&self, query: &str, cx: &mut ModelContext<Self>) -> Task<Result<Vec<Symbol>>> {
2588        let language_registry = self.languages.clone();
2589
2590        if let Some((upstream_client, project_id)) = self.upstream_client().as_ref() {
2591            let request = upstream_client.request(proto::GetProjectSymbols {
2592                project_id: *project_id,
2593                query: query.to_string(),
2594            });
2595            cx.foreground_executor().spawn(async move {
2596                let response = request.await?;
2597                let mut symbols = Vec::new();
2598                let core_symbols = response
2599                    .symbols
2600                    .into_iter()
2601                    .filter_map(|symbol| Self::deserialize_symbol(symbol).log_err())
2602                    .collect::<Vec<_>>();
2603                populate_labels_for_symbols(
2604                    core_symbols,
2605                    &language_registry,
2606                    None,
2607                    None,
2608                    &mut symbols,
2609                )
2610                .await;
2611                Ok(symbols)
2612            })
2613        } else {
2614            struct WorkspaceSymbolsResult {
2615                lsp_adapter: Arc<CachedLspAdapter>,
2616                language: LanguageName,
2617                worktree: WeakModel<Worktree>,
2618                worktree_abs_path: Arc<Path>,
2619                lsp_symbols: Vec<(String, SymbolKind, lsp::Location)>,
2620            }
2621
2622            let mut requests = Vec::new();
2623            for ((worktree_id, _), server_id) in self.language_server_ids.iter() {
2624                let Some(worktree_handle) = self
2625                    .worktree_store
2626                    .read(cx)
2627                    .worktree_for_id(*worktree_id, cx)
2628                else {
2629                    continue;
2630                };
2631                let worktree = worktree_handle.read(cx);
2632                if !worktree.is_visible() {
2633                    continue;
2634                }
2635                let worktree_abs_path = worktree.abs_path().clone();
2636
2637                let (lsp_adapter, language, server) =
2638                    match self.as_local().unwrap().language_servers.get(server_id) {
2639                        Some(LanguageServerState::Running {
2640                            adapter,
2641                            language,
2642                            server,
2643                            ..
2644                        }) => (adapter.clone(), language.clone(), server),
2645
2646                        _ => continue,
2647                    };
2648
2649                requests.push(
2650                    server
2651                        .request::<lsp::request::WorkspaceSymbolRequest>(
2652                            lsp::WorkspaceSymbolParams {
2653                                query: query.to_string(),
2654                                ..Default::default()
2655                            },
2656                        )
2657                        .log_err()
2658                        .map(move |response| {
2659                            let lsp_symbols = response.flatten().map(|symbol_response| match symbol_response {
2660                                lsp::WorkspaceSymbolResponse::Flat(flat_responses) => {
2661                                    flat_responses.into_iter().map(|lsp_symbol| {
2662                                        (lsp_symbol.name, lsp_symbol.kind, lsp_symbol.location)
2663                                    }).collect::<Vec<_>>()
2664                                }
2665                                lsp::WorkspaceSymbolResponse::Nested(nested_responses) => {
2666                                    nested_responses.into_iter().filter_map(|lsp_symbol| {
2667                                        let location = match lsp_symbol.location {
2668                                            OneOf::Left(location) => location,
2669                                            OneOf::Right(_) => {
2670                                                log::error!("Unexpected: client capabilities forbid symbol resolutions in workspace.symbol.resolveSupport");
2671                                                return None
2672                                            }
2673                                        };
2674                                        Some((lsp_symbol.name, lsp_symbol.kind, location))
2675                                    }).collect::<Vec<_>>()
2676                                }
2677                            }).unwrap_or_default();
2678
2679                            WorkspaceSymbolsResult {
2680                                lsp_adapter,
2681                                language,
2682                                worktree: worktree_handle.downgrade(),
2683                                worktree_abs_path,
2684                                lsp_symbols,
2685                            }
2686                        }),
2687                );
2688            }
2689
2690            cx.spawn(move |this, mut cx| async move {
2691                let responses = futures::future::join_all(requests).await;
2692                let this = match this.upgrade() {
2693                    Some(this) => this,
2694                    None => return Ok(Vec::new()),
2695                };
2696
2697                let mut symbols = Vec::new();
2698                for result in responses {
2699                    let core_symbols = this.update(&mut cx, |this, cx| {
2700                        result
2701                            .lsp_symbols
2702                            .into_iter()
2703                            .filter_map(|(symbol_name, symbol_kind, symbol_location)| {
2704                                let abs_path = symbol_location.uri.to_file_path().ok()?;
2705                                let source_worktree = result.worktree.upgrade()?;
2706                                let source_worktree_id = source_worktree.read(cx).id();
2707
2708                                let path;
2709                                let worktree;
2710                                if let Some((tree, rel_path)) =
2711                                    this.worktree_store.read(cx).find_worktree(&abs_path, cx)
2712                                {
2713                                    worktree = tree;
2714                                    path = rel_path;
2715                                } else {
2716                                    worktree = source_worktree.clone();
2717                                    path = relativize_path(&result.worktree_abs_path, &abs_path);
2718                                }
2719
2720                                let worktree_id = worktree.read(cx).id();
2721                                let project_path = ProjectPath {
2722                                    worktree_id,
2723                                    path: path.into(),
2724                                };
2725                                let signature = this.symbol_signature(&project_path);
2726                                Some(CoreSymbol {
2727                                    language_server_name: result.lsp_adapter.name.clone(),
2728                                    source_worktree_id,
2729                                    path: project_path,
2730                                    kind: symbol_kind,
2731                                    name: symbol_name,
2732                                    range: range_from_lsp(symbol_location.range),
2733                                    signature,
2734                                })
2735                            })
2736                            .collect()
2737                    })?;
2738
2739                    populate_labels_for_symbols(
2740                        core_symbols,
2741                        &language_registry,
2742                        Some(result.language),
2743                        Some(result.lsp_adapter),
2744                        &mut symbols,
2745                    )
2746                    .await;
2747                }
2748
2749                Ok(symbols)
2750            })
2751        }
2752    }
2753
2754    pub fn diagnostic_summaries<'a>(
2755        &'a self,
2756        include_ignored: bool,
2757        cx: &'a AppContext,
2758    ) -> impl Iterator<Item = (ProjectPath, LanguageServerId, DiagnosticSummary)> + 'a {
2759        self.worktree_store
2760            .read(cx)
2761            .visible_worktrees(cx)
2762            .filter_map(|worktree| {
2763                let worktree = worktree.read(cx);
2764                Some((worktree, self.diagnostic_summaries.get(&worktree.id())?))
2765            })
2766            .flat_map(move |(worktree, summaries)| {
2767                let worktree_id = worktree.id();
2768                summaries
2769                    .iter()
2770                    .filter(move |(path, _)| {
2771                        include_ignored
2772                            || worktree
2773                                .entry_for_path(path.as_ref())
2774                                .map_or(false, |entry| !entry.is_ignored)
2775                    })
2776                    .flat_map(move |(path, summaries)| {
2777                        summaries.iter().map(move |(server_id, summary)| {
2778                            (
2779                                ProjectPath {
2780                                    worktree_id,
2781                                    path: path.clone(),
2782                                },
2783                                *server_id,
2784                                *summary,
2785                            )
2786                        })
2787                    })
2788            })
2789    }
2790
2791    pub fn started_language_servers(&self) -> Vec<(WorktreeId, LanguageServerName)> {
2792        self.language_server_ids.keys().cloned().collect()
2793    }
2794
2795    pub fn on_buffer_edited(
2796        &mut self,
2797        buffer: Model<Buffer>,
2798        cx: &mut ModelContext<Self>,
2799    ) -> Option<()> {
2800        let buffer = buffer.read(cx);
2801        let file = File::from_dyn(buffer.file())?;
2802        let abs_path = file.as_local()?.abs_path(cx);
2803        let uri = lsp::Url::from_file_path(abs_path).unwrap();
2804        let next_snapshot = buffer.text_snapshot();
2805
2806        let language_servers: Vec<_> = self
2807            .language_servers_for_buffer(buffer, cx)
2808            .map(|i| i.1.clone())
2809            .collect();
2810
2811        for language_server in language_servers {
2812            let language_server = language_server.clone();
2813
2814            let buffer_snapshots = self
2815                .buffer_snapshots
2816                .get_mut(&buffer.remote_id())
2817                .and_then(|m| m.get_mut(&language_server.server_id()))?;
2818            let previous_snapshot = buffer_snapshots.last()?;
2819
2820            let build_incremental_change = || {
2821                buffer
2822                    .edits_since::<(PointUtf16, usize)>(previous_snapshot.snapshot.version())
2823                    .map(|edit| {
2824                        let edit_start = edit.new.start.0;
2825                        let edit_end = edit_start + (edit.old.end.0 - edit.old.start.0);
2826                        let new_text = next_snapshot
2827                            .text_for_range(edit.new.start.1..edit.new.end.1)
2828                            .collect();
2829                        lsp::TextDocumentContentChangeEvent {
2830                            range: Some(lsp::Range::new(
2831                                point_to_lsp(edit_start),
2832                                point_to_lsp(edit_end),
2833                            )),
2834                            range_length: None,
2835                            text: new_text,
2836                        }
2837                    })
2838                    .collect()
2839            };
2840
2841            let document_sync_kind = language_server
2842                .capabilities()
2843                .text_document_sync
2844                .as_ref()
2845                .and_then(|sync| match sync {
2846                    lsp::TextDocumentSyncCapability::Kind(kind) => Some(*kind),
2847                    lsp::TextDocumentSyncCapability::Options(options) => options.change,
2848                });
2849
2850            let content_changes: Vec<_> = match document_sync_kind {
2851                Some(lsp::TextDocumentSyncKind::FULL) => {
2852                    vec![lsp::TextDocumentContentChangeEvent {
2853                        range: None,
2854                        range_length: None,
2855                        text: next_snapshot.text(),
2856                    }]
2857                }
2858                Some(lsp::TextDocumentSyncKind::INCREMENTAL) => build_incremental_change(),
2859                _ => {
2860                    #[cfg(any(test, feature = "test-support"))]
2861                    {
2862                        build_incremental_change()
2863                    }
2864
2865                    #[cfg(not(any(test, feature = "test-support")))]
2866                    {
2867                        continue;
2868                    }
2869                }
2870            };
2871
2872            let next_version = previous_snapshot.version + 1;
2873            buffer_snapshots.push(LspBufferSnapshot {
2874                version: next_version,
2875                snapshot: next_snapshot.clone(),
2876            });
2877
2878            language_server
2879                .notify::<lsp::notification::DidChangeTextDocument>(
2880                    lsp::DidChangeTextDocumentParams {
2881                        text_document: lsp::VersionedTextDocumentIdentifier::new(
2882                            uri.clone(),
2883                            next_version,
2884                        ),
2885                        content_changes,
2886                    },
2887                )
2888                .log_err();
2889        }
2890
2891        None
2892    }
2893
2894    pub fn on_buffer_saved(
2895        &mut self,
2896        buffer: Model<Buffer>,
2897        cx: &mut ModelContext<Self>,
2898    ) -> Option<()> {
2899        let file = File::from_dyn(buffer.read(cx).file())?;
2900        let worktree_id = file.worktree_id(cx);
2901        let abs_path = file.as_local()?.abs_path(cx);
2902        let worktree_path = file.as_local()?.path();
2903        let text_document = lsp::TextDocumentIdentifier {
2904            uri: lsp::Url::from_file_path(abs_path).log_err()?,
2905        };
2906
2907        let watched_paths_for_server = &self.as_local()?.language_server_watched_paths;
2908        for server in self.language_servers_for_worktree(worktree_id) {
2909            let should_notify = maybe!({
2910                Some(
2911                    watched_paths_for_server
2912                        .get(&server.server_id())?
2913                        .read(cx)
2914                        .worktree_paths
2915                        .get(&worktree_id)?
2916                        .is_match(worktree_path),
2917                )
2918            })
2919            .unwrap_or_default();
2920            if !should_notify {
2921                continue;
2922            }
2923            if let Some(include_text) = include_text(server.as_ref()) {
2924                let text = if include_text {
2925                    Some(buffer.read(cx).text())
2926                } else {
2927                    None
2928                };
2929                server
2930                    .notify::<lsp::notification::DidSaveTextDocument>(
2931                        lsp::DidSaveTextDocumentParams {
2932                            text_document: text_document.clone(),
2933                            text,
2934                        },
2935                    )
2936                    .log_err();
2937            }
2938        }
2939
2940        for language_server_id in self.language_server_ids_for_buffer(buffer.read(cx), cx) {
2941            self.simulate_disk_based_diagnostics_events_if_needed(language_server_id, cx);
2942        }
2943
2944        None
2945    }
2946
2947    fn maintain_workspace_config(cx: &mut ModelContext<Self>) -> Task<Result<()>> {
2948        let (mut settings_changed_tx, mut settings_changed_rx) = watch::channel();
2949        let _ = postage::stream::Stream::try_recv(&mut settings_changed_rx);
2950
2951        let settings_observation = cx.observe_global::<SettingsStore>(move |_, _| {
2952            *settings_changed_tx.borrow_mut() = ();
2953        });
2954
2955        cx.spawn(move |this, mut cx| async move {
2956            while let Some(()) = settings_changed_rx.next().await {
2957                let servers = this.update(&mut cx, |this, cx| {
2958                    this.language_server_ids
2959                        .iter()
2960                        .filter_map(|((worktree_id, _), server_id)| {
2961                            let worktree = this
2962                                .worktree_store
2963                                .read(cx)
2964                                .worktree_for_id(*worktree_id, cx)?;
2965                            let state = this.as_local()?.language_servers.get(server_id)?;
2966                            let delegate = LocalLspAdapterDelegate::for_local(this, &worktree, cx);
2967                            match state {
2968                                LanguageServerState::Starting(_) => None,
2969                                LanguageServerState::Running {
2970                                    adapter, server, ..
2971                                } => Some((
2972                                    adapter.adapter.clone(),
2973                                    server.clone(),
2974                                    delegate as Arc<dyn LspAdapterDelegate>,
2975                                )),
2976                            }
2977                        })
2978                        .collect::<Vec<_>>()
2979                })?;
2980
2981                for (adapter, server, delegate) in servers {
2982                    let settings = adapter.workspace_configuration(&delegate, &mut cx).await?;
2983
2984                    server
2985                        .notify::<lsp::notification::DidChangeConfiguration>(
2986                            lsp::DidChangeConfigurationParams { settings },
2987                        )
2988                        .ok();
2989                }
2990            }
2991
2992            drop(settings_observation);
2993            anyhow::Ok(())
2994        })
2995    }
2996
2997    fn primary_language_server_for_buffer<'a>(
2998        &'a self,
2999        buffer: &'a Buffer,
3000        cx: &'a AppContext,
3001    ) -> Option<(&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
3002        // The list of language servers is ordered based on the `language_servers` setting
3003        // for each language, thus we can consider the first one in the list to be the
3004        // primary one.
3005        self.language_servers_for_buffer(buffer, cx).next()
3006    }
3007
3008    pub fn language_server_for_buffer<'a>(
3009        &'a self,
3010        buffer: &'a Buffer,
3011        server_id: LanguageServerId,
3012        cx: &'a AppContext,
3013    ) -> Option<(&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
3014        self.language_servers_for_buffer(buffer, cx)
3015            .find(|(_, s)| s.server_id() == server_id)
3016    }
3017
3018    fn language_servers_for_worktree(
3019        &self,
3020        worktree_id: WorktreeId,
3021    ) -> impl Iterator<Item = &Arc<LanguageServer>> {
3022        self.language_server_ids
3023            .iter()
3024            .filter_map(move |((language_server_worktree_id, _), id)| {
3025                if *language_server_worktree_id == worktree_id {
3026                    if let Some(LanguageServerState::Running { server, .. }) =
3027                        self.as_local()?.language_servers.get(id)
3028                    {
3029                        return Some(server);
3030                    }
3031                }
3032                None
3033            })
3034    }
3035
3036    fn remove_worktree(&mut self, id_to_remove: WorktreeId, cx: &mut ModelContext<Self>) {
3037        self.diagnostics.remove(&id_to_remove);
3038        self.diagnostic_summaries.remove(&id_to_remove);
3039
3040        let mut servers_to_remove = HashMap::default();
3041        let mut servers_to_preserve = HashSet::default();
3042        for ((worktree_id, server_name), &server_id) in &self.language_server_ids {
3043            if worktree_id == &id_to_remove {
3044                servers_to_remove.insert(server_id, server_name.clone());
3045            } else {
3046                servers_to_preserve.insert(server_id);
3047            }
3048        }
3049        servers_to_remove.retain(|server_id, _| !servers_to_preserve.contains(server_id));
3050        for (server_id_to_remove, server_name) in servers_to_remove {
3051            self.language_server_ids
3052                .remove(&(id_to_remove, server_name));
3053            self.language_server_statuses.remove(&server_id_to_remove);
3054            if let Some(local_lsp_store) = self.as_local_mut() {
3055                local_lsp_store
3056                    .language_server_watched_paths
3057                    .remove(&server_id_to_remove);
3058                local_lsp_store
3059                    .last_workspace_edits_by_language_server
3060                    .remove(&server_id_to_remove);
3061                local_lsp_store
3062                    .language_servers
3063                    .remove(&server_id_to_remove);
3064            }
3065            cx.emit(LspStoreEvent::LanguageServerRemoved(server_id_to_remove));
3066        }
3067
3068        if let Some(local) = self.as_local() {
3069            local.prettier_store.update(cx, |prettier_store, cx| {
3070                prettier_store.remove_worktree(id_to_remove, cx);
3071            })
3072        }
3073    }
3074
3075    pub fn shared(
3076        &mut self,
3077        project_id: u64,
3078        downstream_client: AnyProtoClient,
3079        _: &mut ModelContext<Self>,
3080    ) {
3081        self.downstream_client = Some((downstream_client.clone(), project_id));
3082
3083        for (server_id, status) in &self.language_server_statuses {
3084            downstream_client
3085                .send(proto::StartLanguageServer {
3086                    project_id,
3087                    server: Some(proto::LanguageServer {
3088                        id: server_id.0 as u64,
3089                        name: status.name.clone(),
3090                    }),
3091                })
3092                .log_err();
3093        }
3094    }
3095
3096    pub fn disconnected_from_host(&mut self) {
3097        self.downstream_client.take();
3098    }
3099
3100    pub fn disconnected_from_ssh_remote(&mut self) {
3101        if let LspStoreMode::Remote(RemoteLspStore {
3102            upstream_client, ..
3103        }) = &mut self.mode
3104        {
3105            upstream_client.take();
3106        }
3107    }
3108
3109    pub(crate) fn set_language_server_statuses_from_proto(
3110        &mut self,
3111        language_servers: Vec<proto::LanguageServer>,
3112    ) {
3113        self.language_server_statuses = language_servers
3114            .into_iter()
3115            .map(|server| {
3116                (
3117                    LanguageServerId(server.id as usize),
3118                    LanguageServerStatus {
3119                        name: server.name,
3120                        pending_work: Default::default(),
3121                        has_pending_diagnostic_updates: false,
3122                        progress_tokens: Default::default(),
3123                    },
3124                )
3125            })
3126            .collect();
3127    }
3128
3129    pub(crate) fn register_language_server(
3130        &mut self,
3131        worktree_id: WorktreeId,
3132        language_server_name: LanguageServerName,
3133        language_server_id: LanguageServerId,
3134    ) {
3135        self.language_server_ids
3136            .insert((worktree_id, language_server_name), language_server_id);
3137    }
3138
3139    #[track_caller]
3140    pub(crate) fn register_buffer_with_language_servers(
3141        &mut self,
3142        buffer_handle: &Model<Buffer>,
3143        cx: &mut ModelContext<Self>,
3144    ) {
3145        let available_language = self.detect_language_for_buffer(buffer_handle, cx);
3146
3147        let buffer = buffer_handle.read(cx);
3148        let buffer_id = buffer.remote_id();
3149
3150        if let Some(file) = File::from_dyn(buffer.file()) {
3151            if !file.is_local() {
3152                return;
3153            }
3154
3155            let abs_path = file.abs_path(cx);
3156            let Some(uri) = lsp::Url::from_file_path(&abs_path).log_err() else {
3157                return;
3158            };
3159            let initial_snapshot = buffer.text_snapshot();
3160            let worktree_id = file.worktree_id(cx);
3161
3162            if let Some(diagnostics) = self.diagnostics.get(&worktree_id) {
3163                for (server_id, diagnostics) in
3164                    diagnostics.get(file.path()).cloned().unwrap_or_default()
3165                {
3166                    self.update_buffer_diagnostics(buffer_handle, server_id, None, diagnostics, cx)
3167                        .log_err();
3168                }
3169            }
3170
3171            if let Some(language) = available_language {
3172                for adapter in self.languages.lsp_adapters(&language.name()) {
3173                    let server = self
3174                        .language_server_ids
3175                        .get(&(worktree_id, adapter.name.clone()))
3176                        .and_then(|id| self.as_local()?.language_servers.get(id))
3177                        .and_then(|server_state| {
3178                            if let LanguageServerState::Running { server, .. } = server_state {
3179                                Some(server.clone())
3180                            } else {
3181                                None
3182                            }
3183                        });
3184                    let server = match server {
3185                        Some(server) => server,
3186                        None => continue,
3187                    };
3188
3189                    server
3190                        .notify::<lsp::notification::DidOpenTextDocument>(
3191                            lsp::DidOpenTextDocumentParams {
3192                                text_document: lsp::TextDocumentItem::new(
3193                                    uri.clone(),
3194                                    adapter.language_id(&language.name()),
3195                                    0,
3196                                    initial_snapshot.text(),
3197                                ),
3198                            },
3199                        )
3200                        .log_err();
3201
3202                    buffer_handle.update(cx, |buffer, cx| {
3203                        buffer.set_completion_triggers(
3204                            server
3205                                .capabilities()
3206                                .completion_provider
3207                                .as_ref()
3208                                .and_then(|provider| provider.trigger_characters.clone())
3209                                .unwrap_or_default(),
3210                            cx,
3211                        );
3212                    });
3213
3214                    let snapshot = LspBufferSnapshot {
3215                        version: 0,
3216                        snapshot: initial_snapshot.clone(),
3217                    };
3218                    self.buffer_snapshots
3219                        .entry(buffer_id)
3220                        .or_default()
3221                        .insert(server.server_id(), vec![snapshot]);
3222                }
3223            }
3224        }
3225    }
3226
3227    pub(crate) fn unregister_buffer_from_language_servers(
3228        &mut self,
3229        buffer: &Model<Buffer>,
3230        old_file: &File,
3231        cx: &mut AppContext,
3232    ) {
3233        let old_path = match old_file.as_local() {
3234            Some(local) => local.abs_path(cx),
3235            None => return,
3236        };
3237
3238        buffer.update(cx, |buffer, cx| {
3239            let worktree_id = old_file.worktree_id(cx);
3240
3241            let ids = &self.language_server_ids;
3242
3243            if let Some(language) = buffer.language().cloned() {
3244                for adapter in self.languages.lsp_adapters(&language.name()) {
3245                    if let Some(server_id) = ids.get(&(worktree_id, adapter.name.clone())) {
3246                        buffer.update_diagnostics(*server_id, DiagnosticSet::new([], buffer), cx);
3247                    }
3248                }
3249            }
3250
3251            self.buffer_snapshots.remove(&buffer.remote_id());
3252            let file_url = lsp::Url::from_file_path(old_path).unwrap();
3253            for (_, language_server) in self.language_servers_for_buffer(buffer, cx) {
3254                language_server
3255                    .notify::<lsp::notification::DidCloseTextDocument>(
3256                        lsp::DidCloseTextDocumentParams {
3257                            text_document: lsp::TextDocumentIdentifier::new(file_url.clone()),
3258                        },
3259                    )
3260                    .log_err();
3261            }
3262        });
3263    }
3264
3265    pub fn update_diagnostic_entries(
3266        &mut self,
3267        server_id: LanguageServerId,
3268        abs_path: PathBuf,
3269        version: Option<i32>,
3270        diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
3271        cx: &mut ModelContext<Self>,
3272    ) -> Result<(), anyhow::Error> {
3273        let (worktree, relative_path) =
3274            self.worktree_store
3275                .read(cx)
3276                .find_worktree(&abs_path, cx)
3277                .ok_or_else(|| anyhow!("no worktree found for diagnostics path {abs_path:?}"))?;
3278
3279        let project_path = ProjectPath {
3280            worktree_id: worktree.read(cx).id(),
3281            path: relative_path.into(),
3282        };
3283
3284        if let Some(buffer) = self.buffer_store.read(cx).get_by_path(&project_path, cx) {
3285            self.update_buffer_diagnostics(&buffer, server_id, version, diagnostics.clone(), cx)?;
3286        }
3287
3288        let updated = worktree.update(cx, |worktree, cx| {
3289            self.update_worktree_diagnostics(
3290                worktree.id(),
3291                server_id,
3292                project_path.path.clone(),
3293                diagnostics,
3294                cx,
3295            )
3296        })?;
3297        if updated {
3298            cx.emit(LspStoreEvent::DiagnosticsUpdated {
3299                language_server_id: server_id,
3300                path: project_path,
3301            })
3302        }
3303        Ok(())
3304    }
3305
3306    fn update_worktree_diagnostics(
3307        &mut self,
3308        worktree_id: WorktreeId,
3309        server_id: LanguageServerId,
3310        worktree_path: Arc<Path>,
3311        diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
3312        _: &mut ModelContext<Worktree>,
3313    ) -> Result<bool> {
3314        let summaries_for_tree = self.diagnostic_summaries.entry(worktree_id).or_default();
3315        let diagnostics_for_tree = self.diagnostics.entry(worktree_id).or_default();
3316        let summaries_by_server_id = summaries_for_tree.entry(worktree_path.clone()).or_default();
3317
3318        let old_summary = summaries_by_server_id
3319            .remove(&server_id)
3320            .unwrap_or_default();
3321
3322        let new_summary = DiagnosticSummary::new(&diagnostics);
3323        if new_summary.is_empty() {
3324            if let Some(diagnostics_by_server_id) = diagnostics_for_tree.get_mut(&worktree_path) {
3325                if let Ok(ix) = diagnostics_by_server_id.binary_search_by_key(&server_id, |e| e.0) {
3326                    diagnostics_by_server_id.remove(ix);
3327                }
3328                if diagnostics_by_server_id.is_empty() {
3329                    diagnostics_for_tree.remove(&worktree_path);
3330                }
3331            }
3332        } else {
3333            summaries_by_server_id.insert(server_id, new_summary);
3334            let diagnostics_by_server_id = diagnostics_for_tree
3335                .entry(worktree_path.clone())
3336                .or_default();
3337            match diagnostics_by_server_id.binary_search_by_key(&server_id, |e| e.0) {
3338                Ok(ix) => {
3339                    diagnostics_by_server_id[ix] = (server_id, diagnostics);
3340                }
3341                Err(ix) => {
3342                    diagnostics_by_server_id.insert(ix, (server_id, diagnostics));
3343                }
3344            }
3345        }
3346
3347        if !old_summary.is_empty() || !new_summary.is_empty() {
3348            if let Some((downstream_client, project_id)) = &self.downstream_client {
3349                downstream_client
3350                    .send(proto::UpdateDiagnosticSummary {
3351                        project_id: *project_id,
3352                        worktree_id: worktree_id.to_proto(),
3353                        summary: Some(proto::DiagnosticSummary {
3354                            path: worktree_path.to_string_lossy().to_string(),
3355                            language_server_id: server_id.0 as u64,
3356                            error_count: new_summary.error_count as u32,
3357                            warning_count: new_summary.warning_count as u32,
3358                        }),
3359                    })
3360                    .log_err();
3361            }
3362        }
3363
3364        Ok(!old_summary.is_empty() || !new_summary.is_empty())
3365    }
3366
3367    pub fn open_buffer_for_symbol(
3368        &mut self,
3369        symbol: &Symbol,
3370        cx: &mut ModelContext<Self>,
3371    ) -> Task<Result<Model<Buffer>>> {
3372        if let Some((client, project_id)) = self.upstream_client() {
3373            let request = client.request(proto::OpenBufferForSymbol {
3374                project_id,
3375                symbol: Some(Self::serialize_symbol(symbol)),
3376            });
3377            cx.spawn(move |this, mut cx| async move {
3378                let response = request.await?;
3379                let buffer_id = BufferId::new(response.buffer_id)?;
3380                this.update(&mut cx, |this, cx| {
3381                    this.wait_for_remote_buffer(buffer_id, cx)
3382                })?
3383                .await
3384            })
3385        } else {
3386            let Some(&language_server_id) = self.language_server_ids.get(&(
3387                symbol.source_worktree_id,
3388                symbol.language_server_name.clone(),
3389            )) else {
3390                return Task::ready(Err(anyhow!(
3391                    "language server for worktree and language not found"
3392                )));
3393            };
3394
3395            let worktree_abs_path = if let Some(worktree_abs_path) = self
3396                .worktree_store
3397                .read(cx)
3398                .worktree_for_id(symbol.path.worktree_id, cx)
3399                .map(|worktree| worktree.read(cx).abs_path())
3400            {
3401                worktree_abs_path
3402            } else {
3403                return Task::ready(Err(anyhow!("worktree not found for symbol")));
3404            };
3405
3406            let symbol_abs_path = resolve_path(&worktree_abs_path, &symbol.path.path);
3407            let symbol_uri = if let Ok(uri) = lsp::Url::from_file_path(symbol_abs_path) {
3408                uri
3409            } else {
3410                return Task::ready(Err(anyhow!("invalid symbol path")));
3411            };
3412
3413            self.open_local_buffer_via_lsp(
3414                symbol_uri,
3415                language_server_id,
3416                symbol.language_server_name.clone(),
3417                cx,
3418            )
3419        }
3420    }
3421
3422    pub fn open_local_buffer_via_lsp(
3423        &mut self,
3424        mut abs_path: lsp::Url,
3425        language_server_id: LanguageServerId,
3426        language_server_name: LanguageServerName,
3427        cx: &mut ModelContext<Self>,
3428    ) -> Task<Result<Model<Buffer>>> {
3429        cx.spawn(move |this, mut cx| async move {
3430            // Escape percent-encoded string.
3431            let current_scheme = abs_path.scheme().to_owned();
3432            let _ = abs_path.set_scheme("file");
3433
3434            let abs_path = abs_path
3435                .to_file_path()
3436                .map_err(|_| anyhow!("can't convert URI to path"))?;
3437            let p = abs_path.clone();
3438            let yarn_worktree = this
3439                .update(&mut cx, move |this, cx| {
3440                    this.as_local().unwrap().yarn.update(cx, |_, cx| {
3441                        cx.spawn(|this, mut cx| async move {
3442                            let t = this
3443                                .update(&mut cx, |this, cx| {
3444                                    this.process_path(&p, &current_scheme, cx)
3445                                })
3446                                .ok()?;
3447                            t.await
3448                        })
3449                    })
3450                })?
3451                .await;
3452            let (worktree_root_target, known_relative_path) =
3453                if let Some((zip_root, relative_path)) = yarn_worktree {
3454                    (zip_root, Some(relative_path))
3455                } else {
3456                    (Arc::<Path>::from(abs_path.as_path()), None)
3457                };
3458            let (worktree, relative_path) = if let Some(result) =
3459                this.update(&mut cx, |this, cx| {
3460                    this.worktree_store.update(cx, |worktree_store, cx| {
3461                        worktree_store.find_worktree(&worktree_root_target, cx)
3462                    })
3463                })? {
3464                let relative_path =
3465                    known_relative_path.unwrap_or_else(|| Arc::<Path>::from(result.1));
3466                (result.0, relative_path)
3467            } else {
3468                let worktree = this
3469                    .update(&mut cx, |this, cx| {
3470                        this.worktree_store.update(cx, |worktree_store, cx| {
3471                            worktree_store.create_worktree(&worktree_root_target, false, cx)
3472                        })
3473                    })?
3474                    .await?;
3475                this.update(&mut cx, |this, cx| {
3476                    this.register_language_server(
3477                        worktree.read(cx).id(),
3478                        language_server_name,
3479                        language_server_id,
3480                    )
3481                })
3482                .ok();
3483                let worktree_root = worktree.update(&mut cx, |this, _| this.abs_path())?;
3484                let relative_path = if let Some(known_path) = known_relative_path {
3485                    known_path
3486                } else {
3487                    abs_path.strip_prefix(worktree_root)?.into()
3488                };
3489                (worktree, relative_path)
3490            };
3491            let project_path = ProjectPath {
3492                worktree_id: worktree.update(&mut cx, |worktree, _| worktree.id())?,
3493                path: relative_path,
3494            };
3495            this.update(&mut cx, |this, cx| {
3496                this.buffer_store().update(cx, |buffer_store, cx| {
3497                    buffer_store.open_buffer(project_path, cx)
3498                })
3499            })?
3500            .await
3501        })
3502    }
3503
3504    pub(crate) fn update_buffer_diagnostics(
3505        &mut self,
3506        buffer: &Model<Buffer>,
3507        server_id: LanguageServerId,
3508        version: Option<i32>,
3509        mut diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
3510        cx: &mut ModelContext<Self>,
3511    ) -> Result<()> {
3512        fn compare_diagnostics(a: &Diagnostic, b: &Diagnostic) -> Ordering {
3513            Ordering::Equal
3514                .then_with(|| b.is_primary.cmp(&a.is_primary))
3515                .then_with(|| a.is_disk_based.cmp(&b.is_disk_based))
3516                .then_with(|| a.severity.cmp(&b.severity))
3517                .then_with(|| a.message.cmp(&b.message))
3518        }
3519
3520        let snapshot = self.buffer_snapshot_for_lsp_version(buffer, server_id, version, cx)?;
3521
3522        diagnostics.sort_unstable_by(|a, b| {
3523            Ordering::Equal
3524                .then_with(|| a.range.start.cmp(&b.range.start))
3525                .then_with(|| b.range.end.cmp(&a.range.end))
3526                .then_with(|| compare_diagnostics(&a.diagnostic, &b.diagnostic))
3527        });
3528
3529        let mut sanitized_diagnostics = Vec::new();
3530        let edits_since_save = Patch::new(
3531            snapshot
3532                .edits_since::<Unclipped<PointUtf16>>(buffer.read(cx).saved_version())
3533                .collect(),
3534        );
3535        for entry in diagnostics {
3536            let start;
3537            let end;
3538            if entry.diagnostic.is_disk_based {
3539                // Some diagnostics are based on files on disk instead of buffers'
3540                // current contents. Adjust these diagnostics' ranges to reflect
3541                // any unsaved edits.
3542                start = edits_since_save.old_to_new(entry.range.start);
3543                end = edits_since_save.old_to_new(entry.range.end);
3544            } else {
3545                start = entry.range.start;
3546                end = entry.range.end;
3547            }
3548
3549            let mut range = snapshot.clip_point_utf16(start, Bias::Left)
3550                ..snapshot.clip_point_utf16(end, Bias::Right);
3551
3552            // Expand empty ranges by one codepoint
3553            if range.start == range.end {
3554                // This will be go to the next boundary when being clipped
3555                range.end.column += 1;
3556                range.end = snapshot.clip_point_utf16(Unclipped(range.end), Bias::Right);
3557                if range.start == range.end && range.end.column > 0 {
3558                    range.start.column -= 1;
3559                    range.start = snapshot.clip_point_utf16(Unclipped(range.start), Bias::Left);
3560                }
3561            }
3562
3563            sanitized_diagnostics.push(DiagnosticEntry {
3564                range,
3565                diagnostic: entry.diagnostic,
3566            });
3567        }
3568        drop(edits_since_save);
3569
3570        let set = DiagnosticSet::new(sanitized_diagnostics, &snapshot);
3571        buffer.update(cx, |buffer, cx| {
3572            buffer.update_diagnostics(server_id, set, cx)
3573        });
3574        Ok(())
3575    }
3576
3577    fn request_multiple_lsp_locally<P, R>(
3578        &self,
3579        buffer: &Model<Buffer>,
3580        position: Option<P>,
3581        request: R,
3582        cx: &mut ModelContext<'_, Self>,
3583    ) -> Task<Vec<R::Response>>
3584    where
3585        P: ToOffset,
3586        R: LspCommand + Clone,
3587        <R::LspRequest as lsp::request::Request>::Result: Send,
3588        <R::LspRequest as lsp::request::Request>::Params: Send,
3589    {
3590        debug_assert!(self.upstream_client().is_none());
3591
3592        let snapshot = buffer.read(cx).snapshot();
3593        let scope = position.and_then(|position| snapshot.language_scope_at(position));
3594        let server_ids = self
3595            .language_servers_for_buffer(buffer.read(cx), cx)
3596            .filter(|(adapter, _)| {
3597                scope
3598                    .as_ref()
3599                    .map(|scope| scope.language_allowed(&adapter.name))
3600                    .unwrap_or(true)
3601            })
3602            .map(|(_, server)| server.server_id())
3603            .collect::<Vec<_>>();
3604
3605        let mut response_results = server_ids
3606            .into_iter()
3607            .map(|server_id| {
3608                self.request_lsp(
3609                    buffer.clone(),
3610                    LanguageServerToQuery::Other(server_id),
3611                    request.clone(),
3612                    cx,
3613                )
3614            })
3615            .collect::<FuturesUnordered<_>>();
3616
3617        cx.spawn(|_, _| async move {
3618            let mut responses = Vec::with_capacity(response_results.len());
3619            while let Some(response_result) = response_results.next().await {
3620                if let Some(response) = response_result.log_err() {
3621                    responses.push(response);
3622                }
3623            }
3624            responses
3625        })
3626    }
3627
3628    async fn handle_lsp_command<T: LspCommand>(
3629        this: Model<Self>,
3630        envelope: TypedEnvelope<T::ProtoRequest>,
3631        mut cx: AsyncAppContext,
3632    ) -> Result<<T::ProtoRequest as proto::RequestMessage>::Response>
3633    where
3634        <T::LspRequest as lsp::request::Request>::Params: Send,
3635        <T::LspRequest as lsp::request::Request>::Result: Send,
3636    {
3637        let sender_id = envelope.original_sender_id().unwrap_or_default();
3638        let buffer_id = T::buffer_id_from_proto(&envelope.payload)?;
3639        let buffer_handle = this.update(&mut cx, |this, cx| {
3640            this.buffer_store.read(cx).get_existing(buffer_id)
3641        })??;
3642        let request = T::from_proto(
3643            envelope.payload,
3644            this.clone(),
3645            buffer_handle.clone(),
3646            cx.clone(),
3647        )
3648        .await?;
3649        let response = this
3650            .update(&mut cx, |this, cx| {
3651                this.request_lsp(
3652                    buffer_handle.clone(),
3653                    LanguageServerToQuery::Primary,
3654                    request,
3655                    cx,
3656                )
3657            })?
3658            .await?;
3659        this.update(&mut cx, |this, cx| {
3660            Ok(T::response_to_proto(
3661                response,
3662                this,
3663                sender_id,
3664                &buffer_handle.read(cx).version(),
3665                cx,
3666            ))
3667        })?
3668    }
3669
3670    async fn handle_multi_lsp_query(
3671        this: Model<Self>,
3672        envelope: TypedEnvelope<proto::MultiLspQuery>,
3673        mut cx: AsyncAppContext,
3674    ) -> Result<proto::MultiLspQueryResponse> {
3675        let response_from_ssh = this.update(&mut cx, |this, _| {
3676            let (upstream_client, project_id) = this.upstream_client()?;
3677            let mut payload = envelope.payload.clone();
3678            payload.project_id = project_id;
3679
3680            Some(upstream_client.request(payload))
3681        })?;
3682        if let Some(response_from_ssh) = response_from_ssh {
3683            return response_from_ssh.await;
3684        }
3685
3686        let sender_id = envelope.original_sender_id().unwrap_or_default();
3687        let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
3688        let version = deserialize_version(&envelope.payload.version);
3689        let buffer = this.update(&mut cx, |this, cx| {
3690            this.buffer_store.read(cx).get_existing(buffer_id)
3691        })??;
3692        buffer
3693            .update(&mut cx, |buffer, _| {
3694                buffer.wait_for_version(version.clone())
3695            })?
3696            .await?;
3697        let buffer_version = buffer.update(&mut cx, |buffer, _| buffer.version())?;
3698        match envelope
3699            .payload
3700            .strategy
3701            .context("invalid request without the strategy")?
3702        {
3703            proto::multi_lsp_query::Strategy::All(_) => {
3704                // currently, there's only one multiple language servers query strategy,
3705                // so just ensure it's specified correctly
3706            }
3707        }
3708        match envelope.payload.request {
3709            Some(proto::multi_lsp_query::Request::GetHover(get_hover)) => {
3710                let get_hover =
3711                    GetHover::from_proto(get_hover, this.clone(), buffer.clone(), cx.clone())
3712                        .await?;
3713                let all_hovers = this
3714                    .update(&mut cx, |this, cx| {
3715                        this.request_multiple_lsp_locally(
3716                            &buffer,
3717                            Some(get_hover.position),
3718                            get_hover,
3719                            cx,
3720                        )
3721                    })?
3722                    .await
3723                    .into_iter()
3724                    .filter_map(|hover| remove_empty_hover_blocks(hover?));
3725                this.update(&mut cx, |project, cx| proto::MultiLspQueryResponse {
3726                    responses: all_hovers
3727                        .map(|hover| proto::LspResponse {
3728                            response: Some(proto::lsp_response::Response::GetHoverResponse(
3729                                GetHover::response_to_proto(
3730                                    Some(hover),
3731                                    project,
3732                                    sender_id,
3733                                    &buffer_version,
3734                                    cx,
3735                                ),
3736                            )),
3737                        })
3738                        .collect(),
3739                })
3740            }
3741            Some(proto::multi_lsp_query::Request::GetCodeActions(get_code_actions)) => {
3742                let get_code_actions = GetCodeActions::from_proto(
3743                    get_code_actions,
3744                    this.clone(),
3745                    buffer.clone(),
3746                    cx.clone(),
3747                )
3748                .await?;
3749
3750                let all_actions = this
3751                    .update(&mut cx, |project, cx| {
3752                        project.request_multiple_lsp_locally(
3753                            &buffer,
3754                            Some(get_code_actions.range.start),
3755                            get_code_actions,
3756                            cx,
3757                        )
3758                    })?
3759                    .await
3760                    .into_iter();
3761
3762                this.update(&mut cx, |project, cx| proto::MultiLspQueryResponse {
3763                    responses: all_actions
3764                        .map(|code_actions| proto::LspResponse {
3765                            response: Some(proto::lsp_response::Response::GetCodeActionsResponse(
3766                                GetCodeActions::response_to_proto(
3767                                    code_actions,
3768                                    project,
3769                                    sender_id,
3770                                    &buffer_version,
3771                                    cx,
3772                                ),
3773                            )),
3774                        })
3775                        .collect(),
3776                })
3777            }
3778            Some(proto::multi_lsp_query::Request::GetSignatureHelp(get_signature_help)) => {
3779                let get_signature_help = GetSignatureHelp::from_proto(
3780                    get_signature_help,
3781                    this.clone(),
3782                    buffer.clone(),
3783                    cx.clone(),
3784                )
3785                .await?;
3786
3787                let all_signatures = this
3788                    .update(&mut cx, |project, cx| {
3789                        project.request_multiple_lsp_locally(
3790                            &buffer,
3791                            Some(get_signature_help.position),
3792                            get_signature_help,
3793                            cx,
3794                        )
3795                    })?
3796                    .await
3797                    .into_iter();
3798
3799                this.update(&mut cx, |project, cx| proto::MultiLspQueryResponse {
3800                    responses: all_signatures
3801                        .map(|signature_help| proto::LspResponse {
3802                            response: Some(
3803                                proto::lsp_response::Response::GetSignatureHelpResponse(
3804                                    GetSignatureHelp::response_to_proto(
3805                                        signature_help,
3806                                        project,
3807                                        sender_id,
3808                                        &buffer_version,
3809                                        cx,
3810                                    ),
3811                                ),
3812                            ),
3813                        })
3814                        .collect(),
3815                })
3816            }
3817            None => anyhow::bail!("empty multi lsp query request"),
3818        }
3819    }
3820
3821    async fn handle_apply_code_action(
3822        this: Model<Self>,
3823        envelope: TypedEnvelope<proto::ApplyCodeAction>,
3824        mut cx: AsyncAppContext,
3825    ) -> Result<proto::ApplyCodeActionResponse> {
3826        let sender_id = envelope.original_sender_id().unwrap_or_default();
3827        let action = Self::deserialize_code_action(
3828            envelope
3829                .payload
3830                .action
3831                .ok_or_else(|| anyhow!("invalid action"))?,
3832        )?;
3833        let apply_code_action = this.update(&mut cx, |this, cx| {
3834            let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
3835            let buffer = this.buffer_store.read(cx).get_existing(buffer_id)?;
3836            anyhow::Ok(this.apply_code_action(buffer, action, false, cx))
3837        })??;
3838
3839        let project_transaction = apply_code_action.await?;
3840        let project_transaction = this.update(&mut cx, |this, cx| {
3841            this.buffer_store.update(cx, |buffer_store, cx| {
3842                buffer_store.serialize_project_transaction_for_peer(
3843                    project_transaction,
3844                    sender_id,
3845                    cx,
3846                )
3847            })
3848        })?;
3849        Ok(proto::ApplyCodeActionResponse {
3850            transaction: Some(project_transaction),
3851        })
3852    }
3853
3854    async fn handle_update_diagnostic_summary(
3855        this: Model<Self>,
3856        envelope: TypedEnvelope<proto::UpdateDiagnosticSummary>,
3857        mut cx: AsyncAppContext,
3858    ) -> Result<()> {
3859        this.update(&mut cx, |this, cx| {
3860            let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
3861            if let Some(message) = envelope.payload.summary {
3862                let project_path = ProjectPath {
3863                    worktree_id,
3864                    path: Path::new(&message.path).into(),
3865                };
3866                let path = project_path.path.clone();
3867                let server_id = LanguageServerId(message.language_server_id as usize);
3868                let summary = DiagnosticSummary {
3869                    error_count: message.error_count as usize,
3870                    warning_count: message.warning_count as usize,
3871                };
3872
3873                if summary.is_empty() {
3874                    if let Some(worktree_summaries) =
3875                        this.diagnostic_summaries.get_mut(&worktree_id)
3876                    {
3877                        if let Some(summaries) = worktree_summaries.get_mut(&path) {
3878                            summaries.remove(&server_id);
3879                            if summaries.is_empty() {
3880                                worktree_summaries.remove(&path);
3881                            }
3882                        }
3883                    }
3884                } else {
3885                    this.diagnostic_summaries
3886                        .entry(worktree_id)
3887                        .or_default()
3888                        .entry(path)
3889                        .or_default()
3890                        .insert(server_id, summary);
3891                }
3892                cx.emit(LspStoreEvent::DiagnosticsUpdated {
3893                    language_server_id: LanguageServerId(message.language_server_id as usize),
3894                    path: project_path,
3895                });
3896            }
3897            Ok(())
3898        })?
3899    }
3900
3901    async fn handle_start_language_server(
3902        this: Model<Self>,
3903        envelope: TypedEnvelope<proto::StartLanguageServer>,
3904        mut cx: AsyncAppContext,
3905    ) -> Result<()> {
3906        let server = envelope
3907            .payload
3908            .server
3909            .ok_or_else(|| anyhow!("invalid server"))?;
3910        this.update(&mut cx, |this, cx| {
3911            this.language_server_statuses.insert(
3912                LanguageServerId(server.id as usize),
3913                LanguageServerStatus {
3914                    name: server.name,
3915                    pending_work: Default::default(),
3916                    has_pending_diagnostic_updates: false,
3917                    progress_tokens: Default::default(),
3918                },
3919            );
3920            cx.notify();
3921        })?;
3922        Ok(())
3923    }
3924
3925    async fn handle_update_language_server(
3926        this: Model<Self>,
3927        envelope: TypedEnvelope<proto::UpdateLanguageServer>,
3928        mut cx: AsyncAppContext,
3929    ) -> Result<()> {
3930        this.update(&mut cx, |this, cx| {
3931            let language_server_id = LanguageServerId(envelope.payload.language_server_id as usize);
3932
3933            match envelope
3934                .payload
3935                .variant
3936                .ok_or_else(|| anyhow!("invalid variant"))?
3937            {
3938                proto::update_language_server::Variant::WorkStart(payload) => {
3939                    this.on_lsp_work_start(
3940                        language_server_id,
3941                        payload.token,
3942                        LanguageServerProgress {
3943                            title: payload.title,
3944                            is_disk_based_diagnostics_progress: false,
3945                            is_cancellable: false,
3946                            message: payload.message,
3947                            percentage: payload.percentage.map(|p| p as usize),
3948                            last_update_at: cx.background_executor().now(),
3949                        },
3950                        cx,
3951                    );
3952                }
3953
3954                proto::update_language_server::Variant::WorkProgress(payload) => {
3955                    this.on_lsp_work_progress(
3956                        language_server_id,
3957                        payload.token,
3958                        LanguageServerProgress {
3959                            title: None,
3960                            is_disk_based_diagnostics_progress: false,
3961                            is_cancellable: false,
3962                            message: payload.message,
3963                            percentage: payload.percentage.map(|p| p as usize),
3964                            last_update_at: cx.background_executor().now(),
3965                        },
3966                        cx,
3967                    );
3968                }
3969
3970                proto::update_language_server::Variant::WorkEnd(payload) => {
3971                    this.on_lsp_work_end(language_server_id, payload.token, cx);
3972                }
3973
3974                proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating(_) => {
3975                    this.disk_based_diagnostics_started(language_server_id, cx);
3976                }
3977
3978                proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(_) => {
3979                    this.disk_based_diagnostics_finished(language_server_id, cx)
3980                }
3981            }
3982
3983            Ok(())
3984        })?
3985    }
3986
3987    pub fn disk_based_diagnostics_started(
3988        &mut self,
3989        language_server_id: LanguageServerId,
3990        cx: &mut ModelContext<Self>,
3991    ) {
3992        if let Some(language_server_status) =
3993            self.language_server_statuses.get_mut(&language_server_id)
3994        {
3995            language_server_status.has_pending_diagnostic_updates = true;
3996        }
3997
3998        cx.emit(LspStoreEvent::DiskBasedDiagnosticsStarted { language_server_id });
3999        cx.emit(LspStoreEvent::LanguageServerUpdate {
4000            language_server_id,
4001            message: proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating(
4002                Default::default(),
4003            ),
4004        })
4005    }
4006
4007    pub fn disk_based_diagnostics_finished(
4008        &mut self,
4009        language_server_id: LanguageServerId,
4010        cx: &mut ModelContext<Self>,
4011    ) {
4012        if let Some(language_server_status) =
4013            self.language_server_statuses.get_mut(&language_server_id)
4014        {
4015            language_server_status.has_pending_diagnostic_updates = false;
4016        }
4017
4018        cx.emit(LspStoreEvent::DiskBasedDiagnosticsFinished { language_server_id });
4019        cx.emit(LspStoreEvent::LanguageServerUpdate {
4020            language_server_id,
4021            message: proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(
4022                Default::default(),
4023            ),
4024        })
4025    }
4026
4027    // After saving a buffer using a language server that doesn't provide a disk-based progress token,
4028    // kick off a timer that will reset every time the buffer is saved. If the timer eventually fires,
4029    // simulate disk-based diagnostics being finished so that other pieces of UI (e.g., project
4030    // diagnostics view, diagnostic status bar) can update. We don't emit an event right away because
4031    // the language server might take some time to publish diagnostics.
4032    fn simulate_disk_based_diagnostics_events_if_needed(
4033        &mut self,
4034        language_server_id: LanguageServerId,
4035        cx: &mut ModelContext<Self>,
4036    ) {
4037        const DISK_BASED_DIAGNOSTICS_DEBOUNCE: Duration = Duration::from_secs(1);
4038
4039        let Some(LanguageServerState::Running {
4040            simulate_disk_based_diagnostics_completion,
4041            adapter,
4042            ..
4043        }) = self
4044            .as_local_mut()
4045            .and_then(|local_store| local_store.language_servers.get_mut(&language_server_id))
4046        else {
4047            return;
4048        };
4049
4050        if adapter.disk_based_diagnostics_progress_token.is_some() {
4051            return;
4052        }
4053
4054        let prev_task = simulate_disk_based_diagnostics_completion.replace(cx.spawn(
4055            move |this, mut cx| async move {
4056                cx.background_executor()
4057                    .timer(DISK_BASED_DIAGNOSTICS_DEBOUNCE)
4058                    .await;
4059
4060                this.update(&mut cx, |this, cx| {
4061                    this.disk_based_diagnostics_finished(language_server_id, cx);
4062
4063                    if let Some(LanguageServerState::Running {
4064                        simulate_disk_based_diagnostics_completion,
4065                        ..
4066                    }) = this.as_local_mut().and_then(|local_store| {
4067                        local_store.language_servers.get_mut(&language_server_id)
4068                    }) {
4069                        *simulate_disk_based_diagnostics_completion = None;
4070                    }
4071                })
4072                .ok();
4073            },
4074        ));
4075
4076        if prev_task.is_none() {
4077            self.disk_based_diagnostics_started(language_server_id, cx);
4078        }
4079    }
4080
4081    pub fn language_server_statuses(
4082        &self,
4083    ) -> impl DoubleEndedIterator<Item = (LanguageServerId, &LanguageServerStatus)> {
4084        self.language_server_statuses
4085            .iter()
4086            .map(|(key, value)| (*key, value))
4087    }
4088
4089    fn lsp_notify_abs_paths_changed(
4090        &mut self,
4091        server_id: LanguageServerId,
4092        changes: Vec<PathEvent>,
4093    ) {
4094        maybe!({
4095            let server = self.language_server_for_id(server_id)?;
4096            let changes = changes
4097                .into_iter()
4098                .filter_map(|event| {
4099                    let typ = match event.kind? {
4100                        PathEventKind::Created => lsp::FileChangeType::CREATED,
4101                        PathEventKind::Removed => lsp::FileChangeType::DELETED,
4102                        PathEventKind::Changed => lsp::FileChangeType::CHANGED,
4103                    };
4104                    Some(lsp::FileEvent {
4105                        uri: lsp::Url::from_file_path(&event.path).ok()?,
4106                        typ,
4107                    })
4108                })
4109                .collect::<Vec<_>>();
4110            if !changes.is_empty() {
4111                server
4112                    .notify::<lsp::notification::DidChangeWatchedFiles>(
4113                        lsp::DidChangeWatchedFilesParams { changes },
4114                    )
4115                    .log_err();
4116            }
4117            Some(())
4118        });
4119    }
4120
4121    fn rebuild_watched_paths(
4122        &mut self,
4123        language_server_id: LanguageServerId,
4124        cx: &mut ModelContext<Self>,
4125    ) {
4126        let worktrees = self
4127            .worktree_store
4128            .read(cx)
4129            .worktrees()
4130            .filter_map(|worktree| {
4131                self.language_servers_for_worktree(worktree.read(cx).id())
4132                    .find(|server| server.server_id() == language_server_id)
4133                    .map(|_| worktree)
4134            })
4135            .collect::<Vec<_>>();
4136
4137        let local_lsp_store = self.as_local_mut().unwrap();
4138
4139        let Some(watchers) = local_lsp_store
4140            .language_server_watcher_registrations
4141            .get(&language_server_id)
4142        else {
4143            return;
4144        };
4145
4146        let mut worktree_globs = HashMap::default();
4147        let mut abs_globs = HashMap::default();
4148        log::trace!(
4149            "Processing new watcher paths for language server with id {}",
4150            language_server_id
4151        );
4152
4153        enum PathToWatch {
4154            Worktree {
4155                literal_prefix: Arc<Path>,
4156                pattern: String,
4157            },
4158            Absolute {
4159                path: Arc<Path>,
4160                pattern: String,
4161            },
4162        }
4163        for watcher in watchers.values().flatten() {
4164            let mut found_host = false;
4165            for worktree in &worktrees {
4166                let glob_is_inside_worktree = worktree.update(cx, |tree, _| {
4167                    if let Some(worktree_root_path) = tree.abs_path().to_str() {
4168                        let path_to_watch = match &watcher.glob_pattern {
4169                            lsp::GlobPattern::String(s) => {
4170                                match s.strip_prefix(worktree_root_path) {
4171                                    Some(relative) => {
4172                                        let pattern = relative
4173                                            .strip_prefix(std::path::MAIN_SEPARATOR)
4174                                            .unwrap_or(relative)
4175                                            .to_owned();
4176                                        let literal_prefix = glob_literal_prefix(&pattern);
4177
4178                                        let literal_prefix = Arc::from(PathBuf::from(
4179                                            literal_prefix
4180                                                .strip_prefix(std::path::MAIN_SEPARATOR)
4181                                                .unwrap_or(literal_prefix),
4182                                        ));
4183                                        PathToWatch::Worktree {
4184                                            literal_prefix,
4185                                            pattern,
4186                                        }
4187                                    }
4188                                    None => {
4189                                        let path = glob_literal_prefix(s);
4190                                        let glob = &s[path.len()..];
4191                                        let pattern = glob
4192                                            .strip_prefix(std::path::MAIN_SEPARATOR)
4193                                            .unwrap_or(glob)
4194                                            .to_owned();
4195                                        let path = if Path::new(path).components().next().is_none()
4196                                        {
4197                                            Arc::from(Path::new(worktree_root_path))
4198                                        } else {
4199                                            PathBuf::from(path).into()
4200                                        };
4201
4202                                        PathToWatch::Absolute { path, pattern }
4203                                    }
4204                                }
4205                            }
4206                            lsp::GlobPattern::Relative(rp) => {
4207                                let Ok(mut base_uri) = match &rp.base_uri {
4208                                    lsp::OneOf::Left(workspace_folder) => &workspace_folder.uri,
4209                                    lsp::OneOf::Right(base_uri) => base_uri,
4210                                }
4211                                .to_file_path() else {
4212                                    return false;
4213                                };
4214
4215                                match base_uri.strip_prefix(worktree_root_path) {
4216                                    Ok(relative) => {
4217                                        let mut literal_prefix = relative.to_owned();
4218                                        literal_prefix.push(glob_literal_prefix(&rp.pattern));
4219
4220                                        PathToWatch::Worktree {
4221                                            literal_prefix: literal_prefix.into(),
4222                                            pattern: rp.pattern.clone(),
4223                                        }
4224                                    }
4225                                    Err(_) => {
4226                                        let path = glob_literal_prefix(&rp.pattern);
4227                                        let glob = &rp.pattern[path.len()..];
4228                                        let pattern = glob
4229                                            .strip_prefix(std::path::MAIN_SEPARATOR)
4230                                            .unwrap_or(glob)
4231                                            .to_owned();
4232                                        base_uri.push(path);
4233
4234                                        let path = if base_uri.components().next().is_none() {
4235                                            Arc::from(Path::new("/"))
4236                                        } else {
4237                                            base_uri.into()
4238                                        };
4239                                        PathToWatch::Absolute { path, pattern }
4240                                    }
4241                                }
4242                            }
4243                        };
4244                        match path_to_watch {
4245                            PathToWatch::Worktree {
4246                                literal_prefix,
4247                                pattern,
4248                            } => {
4249                                if let Some((tree, glob)) =
4250                                    tree.as_local_mut().zip(Glob::new(&pattern).log_err())
4251                                {
4252                                    tree.add_path_prefix_to_scan(literal_prefix);
4253                                    worktree_globs
4254                                        .entry(tree.id())
4255                                        .or_insert_with(GlobSetBuilder::new)
4256                                        .add(glob);
4257                                } else {
4258                                    return false;
4259                                }
4260                            }
4261                            PathToWatch::Absolute { path, pattern } => {
4262                                if let Some(glob) = Glob::new(&pattern).log_err() {
4263                                    abs_globs
4264                                        .entry(path)
4265                                        .or_insert_with(GlobSetBuilder::new)
4266                                        .add(glob);
4267                                }
4268                            }
4269                        }
4270                        return true;
4271                    }
4272                    false
4273                });
4274                if glob_is_inside_worktree {
4275                    log::trace!(
4276                        "Watcher pattern `{}` has been attached to the worktree at `{}`",
4277                        serde_json::to_string(&watcher.glob_pattern).unwrap(),
4278                        worktree.read(cx).abs_path().display()
4279                    );
4280                    found_host = true;
4281                }
4282            }
4283            if !found_host {
4284                log::error!(
4285                    "Watcher pattern `{}` has not been attached to any worktree or absolute path",
4286                    serde_json::to_string(&watcher.glob_pattern).unwrap()
4287                )
4288            }
4289        }
4290
4291        let mut watch_builder = LanguageServerWatchedPathsBuilder::default();
4292        for (worktree_id, builder) in worktree_globs {
4293            if let Ok(globset) = builder.build() {
4294                watch_builder.watch_worktree(worktree_id, globset);
4295            }
4296        }
4297        for (abs_path, builder) in abs_globs {
4298            if let Ok(globset) = builder.build() {
4299                watch_builder.watch_abs_path(abs_path, globset);
4300            }
4301        }
4302        let watcher = watch_builder.build(local_lsp_store.fs.clone(), language_server_id, cx);
4303        local_lsp_store
4304            .language_server_watched_paths
4305            .insert(language_server_id, watcher);
4306
4307        cx.notify();
4308    }
4309
4310    pub fn language_server_for_id(&self, id: LanguageServerId) -> Option<Arc<LanguageServer>> {
4311        if let Some(local_lsp_store) = self.as_local() {
4312            if let Some(LanguageServerState::Running { server, .. }) =
4313                local_lsp_store.language_servers.get(&id)
4314            {
4315                Some(server.clone())
4316            } else if let Some((_, server)) =
4317                local_lsp_store.supplementary_language_servers.get(&id)
4318            {
4319                Some(Arc::clone(server))
4320            } else {
4321                None
4322            }
4323        } else {
4324            None
4325        }
4326    }
4327
4328    async fn on_lsp_workspace_edit(
4329        this: WeakModel<Self>,
4330        params: lsp::ApplyWorkspaceEditParams,
4331        server_id: LanguageServerId,
4332        adapter: Arc<CachedLspAdapter>,
4333        mut cx: AsyncAppContext,
4334    ) -> Result<lsp::ApplyWorkspaceEditResponse> {
4335        let this = this
4336            .upgrade()
4337            .ok_or_else(|| anyhow!("project project closed"))?;
4338        let language_server = this
4339            .update(&mut cx, |this, _| this.language_server_for_id(server_id))?
4340            .ok_or_else(|| anyhow!("language server not found"))?;
4341        let transaction = Self::deserialize_workspace_edit(
4342            this.clone(),
4343            params.edit,
4344            true,
4345            adapter.clone(),
4346            language_server.clone(),
4347            &mut cx,
4348        )
4349        .await
4350        .log_err();
4351        this.update(&mut cx, |this, _| {
4352            if let Some(transaction) = transaction {
4353                this.as_local_mut()
4354                    .unwrap()
4355                    .last_workspace_edits_by_language_server
4356                    .insert(server_id, transaction);
4357            }
4358        })?;
4359        Ok(lsp::ApplyWorkspaceEditResponse {
4360            applied: true,
4361            failed_change: None,
4362            failure_reason: None,
4363        })
4364    }
4365
4366    fn on_lsp_progress(
4367        &mut self,
4368        progress: lsp::ProgressParams,
4369        language_server_id: LanguageServerId,
4370        disk_based_diagnostics_progress_token: Option<String>,
4371        cx: &mut ModelContext<Self>,
4372    ) {
4373        let token = match progress.token {
4374            lsp::NumberOrString::String(token) => token,
4375            lsp::NumberOrString::Number(token) => {
4376                log::info!("skipping numeric progress token {}", token);
4377                return;
4378            }
4379        };
4380
4381        let lsp::ProgressParamsValue::WorkDone(progress) = progress.value;
4382        let language_server_status =
4383            if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
4384                status
4385            } else {
4386                return;
4387            };
4388
4389        if !language_server_status.progress_tokens.contains(&token) {
4390            return;
4391        }
4392
4393        let is_disk_based_diagnostics_progress = disk_based_diagnostics_progress_token
4394            .as_ref()
4395            .map_or(false, |disk_based_token| {
4396                token.starts_with(disk_based_token)
4397            });
4398
4399        match progress {
4400            lsp::WorkDoneProgress::Begin(report) => {
4401                if is_disk_based_diagnostics_progress {
4402                    self.disk_based_diagnostics_started(language_server_id, cx);
4403                }
4404                self.on_lsp_work_start(
4405                    language_server_id,
4406                    token.clone(),
4407                    LanguageServerProgress {
4408                        title: Some(report.title),
4409                        is_disk_based_diagnostics_progress,
4410                        is_cancellable: report.cancellable.unwrap_or(false),
4411                        message: report.message.clone(),
4412                        percentage: report.percentage.map(|p| p as usize),
4413                        last_update_at: cx.background_executor().now(),
4414                    },
4415                    cx,
4416                );
4417            }
4418            lsp::WorkDoneProgress::Report(report) => {
4419                if self.on_lsp_work_progress(
4420                    language_server_id,
4421                    token.clone(),
4422                    LanguageServerProgress {
4423                        title: None,
4424                        is_disk_based_diagnostics_progress,
4425                        is_cancellable: report.cancellable.unwrap_or(false),
4426                        message: report.message.clone(),
4427                        percentage: report.percentage.map(|p| p as usize),
4428                        last_update_at: cx.background_executor().now(),
4429                    },
4430                    cx,
4431                ) {
4432                    cx.emit(LspStoreEvent::LanguageServerUpdate {
4433                        language_server_id,
4434                        message: proto::update_language_server::Variant::WorkProgress(
4435                            proto::LspWorkProgress {
4436                                token,
4437                                message: report.message,
4438                                percentage: report.percentage,
4439                            },
4440                        ),
4441                    })
4442                }
4443            }
4444            lsp::WorkDoneProgress::End(_) => {
4445                language_server_status.progress_tokens.remove(&token);
4446                self.on_lsp_work_end(language_server_id, token.clone(), cx);
4447                if is_disk_based_diagnostics_progress {
4448                    self.disk_based_diagnostics_finished(language_server_id, cx);
4449                }
4450            }
4451        }
4452    }
4453
4454    fn on_lsp_work_start(
4455        &mut self,
4456        language_server_id: LanguageServerId,
4457        token: String,
4458        progress: LanguageServerProgress,
4459        cx: &mut ModelContext<Self>,
4460    ) {
4461        if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
4462            status.pending_work.insert(token.clone(), progress.clone());
4463            cx.notify();
4464        }
4465        cx.emit(LspStoreEvent::LanguageServerUpdate {
4466            language_server_id,
4467            message: proto::update_language_server::Variant::WorkStart(proto::LspWorkStart {
4468                token,
4469                title: progress.title,
4470                message: progress.message,
4471                percentage: progress.percentage.map(|p| p as u32),
4472            }),
4473        })
4474    }
4475
4476    fn on_lsp_work_progress(
4477        &mut self,
4478        language_server_id: LanguageServerId,
4479        token: String,
4480        progress: LanguageServerProgress,
4481        cx: &mut ModelContext<Self>,
4482    ) -> bool {
4483        if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
4484            match status.pending_work.entry(token) {
4485                btree_map::Entry::Vacant(entry) => {
4486                    entry.insert(progress);
4487                    cx.notify();
4488                    return true;
4489                }
4490                btree_map::Entry::Occupied(mut entry) => {
4491                    let entry = entry.get_mut();
4492                    if (progress.last_update_at - entry.last_update_at)
4493                        >= SERVER_PROGRESS_THROTTLE_TIMEOUT
4494                    {
4495                        entry.last_update_at = progress.last_update_at;
4496                        if progress.message.is_some() {
4497                            entry.message = progress.message;
4498                        }
4499                        if progress.percentage.is_some() {
4500                            entry.percentage = progress.percentage;
4501                        }
4502                        cx.notify();
4503                        return true;
4504                    }
4505                }
4506            }
4507        }
4508
4509        false
4510    }
4511
4512    fn on_lsp_work_end(
4513        &mut self,
4514        language_server_id: LanguageServerId,
4515        token: String,
4516        cx: &mut ModelContext<Self>,
4517    ) {
4518        if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) {
4519            if let Some(work) = status.pending_work.remove(&token) {
4520                if !work.is_disk_based_diagnostics_progress {
4521                    cx.emit(LspStoreEvent::RefreshInlayHints);
4522                }
4523            }
4524            cx.notify();
4525        }
4526
4527        cx.emit(LspStoreEvent::LanguageServerUpdate {
4528            language_server_id,
4529            message: proto::update_language_server::Variant::WorkEnd(proto::LspWorkEnd { token }),
4530        })
4531    }
4532
4533    fn on_lsp_did_change_watched_files(
4534        &mut self,
4535        language_server_id: LanguageServerId,
4536        registration_id: &str,
4537        params: DidChangeWatchedFilesRegistrationOptions,
4538        cx: &mut ModelContext<Self>,
4539    ) {
4540        if let Some(local) = self.as_local_mut() {
4541            let registrations = local
4542                .language_server_watcher_registrations
4543                .entry(language_server_id)
4544                .or_default();
4545
4546            registrations.insert(registration_id.to_string(), params.watchers);
4547
4548            self.rebuild_watched_paths(language_server_id, cx);
4549        }
4550    }
4551
4552    fn on_lsp_unregister_did_change_watched_files(
4553        &mut self,
4554        language_server_id: LanguageServerId,
4555        registration_id: &str,
4556        cx: &mut ModelContext<Self>,
4557    ) {
4558        if let Some(local) = self.as_local_mut() {
4559            let registrations = local
4560                .language_server_watcher_registrations
4561                .entry(language_server_id)
4562                .or_default();
4563
4564            if registrations.remove(registration_id).is_some() {
4565                log::info!(
4566                "language server {}: unregistered workspace/DidChangeWatchedFiles capability with id {}",
4567                language_server_id,
4568                registration_id
4569            );
4570            } else {
4571                log::warn!(
4572                "language server {}: failed to unregister workspace/DidChangeWatchedFiles capability with id {}. not registered.",
4573                language_server_id,
4574                registration_id
4575            );
4576            }
4577
4578            self.rebuild_watched_paths(language_server_id, cx);
4579        }
4580    }
4581
4582    #[allow(clippy::type_complexity)]
4583    pub(crate) fn edits_from_lsp(
4584        &mut self,
4585        buffer: &Model<Buffer>,
4586        lsp_edits: impl 'static + Send + IntoIterator<Item = lsp::TextEdit>,
4587        server_id: LanguageServerId,
4588        version: Option<i32>,
4589        cx: &mut ModelContext<Self>,
4590    ) -> Task<Result<Vec<(Range<Anchor>, String)>>> {
4591        let snapshot = self.buffer_snapshot_for_lsp_version(buffer, server_id, version, cx);
4592        cx.background_executor().spawn(async move {
4593            let snapshot = snapshot?;
4594            let mut lsp_edits = lsp_edits
4595                .into_iter()
4596                .map(|edit| (range_from_lsp(edit.range), edit.new_text))
4597                .collect::<Vec<_>>();
4598            lsp_edits.sort_by_key(|(range, _)| range.start);
4599
4600            let mut lsp_edits = lsp_edits.into_iter().peekable();
4601            let mut edits = Vec::new();
4602            while let Some((range, mut new_text)) = lsp_edits.next() {
4603                // Clip invalid ranges provided by the language server.
4604                let mut range = snapshot.clip_point_utf16(range.start, Bias::Left)
4605                    ..snapshot.clip_point_utf16(range.end, Bias::Left);
4606
4607                // Combine any LSP edits that are adjacent.
4608                //
4609                // Also, combine LSP edits that are separated from each other by only
4610                // a newline. This is important because for some code actions,
4611                // Rust-analyzer rewrites the entire buffer via a series of edits that
4612                // are separated by unchanged newline characters.
4613                //
4614                // In order for the diffing logic below to work properly, any edits that
4615                // cancel each other out must be combined into one.
4616                while let Some((next_range, next_text)) = lsp_edits.peek() {
4617                    if next_range.start.0 > range.end {
4618                        if next_range.start.0.row > range.end.row + 1
4619                            || next_range.start.0.column > 0
4620                            || snapshot.clip_point_utf16(
4621                                Unclipped(PointUtf16::new(range.end.row, u32::MAX)),
4622                                Bias::Left,
4623                            ) > range.end
4624                        {
4625                            break;
4626                        }
4627                        new_text.push('\n');
4628                    }
4629                    range.end = snapshot.clip_point_utf16(next_range.end, Bias::Left);
4630                    new_text.push_str(next_text);
4631                    lsp_edits.next();
4632                }
4633
4634                // For multiline edits, perform a diff of the old and new text so that
4635                // we can identify the changes more precisely, preserving the locations
4636                // of any anchors positioned in the unchanged regions.
4637                if range.end.row > range.start.row {
4638                    let mut offset = range.start.to_offset(&snapshot);
4639                    let old_text = snapshot.text_for_range(range).collect::<String>();
4640
4641                    let diff = TextDiff::from_lines(old_text.as_str(), &new_text);
4642                    let mut moved_since_edit = true;
4643                    for change in diff.iter_all_changes() {
4644                        let tag = change.tag();
4645                        let value = change.value();
4646                        match tag {
4647                            ChangeTag::Equal => {
4648                                offset += value.len();
4649                                moved_since_edit = true;
4650                            }
4651                            ChangeTag::Delete => {
4652                                let start = snapshot.anchor_after(offset);
4653                                let end = snapshot.anchor_before(offset + value.len());
4654                                if moved_since_edit {
4655                                    edits.push((start..end, String::new()));
4656                                } else {
4657                                    edits.last_mut().unwrap().0.end = end;
4658                                }
4659                                offset += value.len();
4660                                moved_since_edit = false;
4661                            }
4662                            ChangeTag::Insert => {
4663                                if moved_since_edit {
4664                                    let anchor = snapshot.anchor_after(offset);
4665                                    edits.push((anchor..anchor, value.to_string()));
4666                                } else {
4667                                    edits.last_mut().unwrap().1.push_str(value);
4668                                }
4669                                moved_since_edit = false;
4670                            }
4671                        }
4672                    }
4673                } else if range.end == range.start {
4674                    let anchor = snapshot.anchor_after(range.start);
4675                    edits.push((anchor..anchor, new_text));
4676                } else {
4677                    let edit_start = snapshot.anchor_after(range.start);
4678                    let edit_end = snapshot.anchor_before(range.end);
4679                    edits.push((edit_start..edit_end, new_text));
4680                }
4681            }
4682
4683            Ok(edits)
4684        })
4685    }
4686
4687    pub async fn handle_resolve_completion_documentation(
4688        this: Model<Self>,
4689        envelope: TypedEnvelope<proto::ResolveCompletionDocumentation>,
4690        mut cx: AsyncAppContext,
4691    ) -> Result<proto::ResolveCompletionDocumentationResponse> {
4692        let lsp_completion = serde_json::from_slice(&envelope.payload.lsp_completion)?;
4693
4694        let completion = this
4695            .read_with(&cx, |this, cx| {
4696                let id = LanguageServerId(envelope.payload.language_server_id as usize);
4697                let Some(server) = this.language_server_for_id(id) else {
4698                    return Err(anyhow!("No language server {id}"));
4699                };
4700
4701                Ok(cx.background_executor().spawn(async move {
4702                    let can_resolve = server
4703                        .capabilities()
4704                        .completion_provider
4705                        .as_ref()
4706                        .and_then(|options| options.resolve_provider)
4707                        .unwrap_or(false);
4708                    if can_resolve {
4709                        server
4710                            .request::<lsp::request::ResolveCompletionItem>(lsp_completion)
4711                            .await
4712                    } else {
4713                        anyhow::Ok(lsp_completion)
4714                    }
4715                }))
4716            })??
4717            .await?;
4718
4719        let mut documentation_is_markdown = false;
4720        let lsp_completion = serde_json::to_string(&completion)?.into_bytes();
4721        let documentation = match completion.documentation {
4722            Some(lsp::Documentation::String(text)) => text,
4723
4724            Some(lsp::Documentation::MarkupContent(lsp::MarkupContent { kind, value })) => {
4725                documentation_is_markdown = kind == lsp::MarkupKind::Markdown;
4726                value
4727            }
4728
4729            _ => String::new(),
4730        };
4731
4732        // If we have a new buffer_id, that means we're talking to a new client
4733        // and want to check for new text_edits in the completion too.
4734        let mut old_start = None;
4735        let mut old_end = None;
4736        let mut new_text = String::default();
4737        if let Ok(buffer_id) = BufferId::new(envelope.payload.buffer_id) {
4738            let buffer_snapshot = this.update(&mut cx, |this, cx| {
4739                let buffer = this.buffer_store.read(cx).get_existing(buffer_id)?;
4740                anyhow::Ok(buffer.read(cx).snapshot())
4741            })??;
4742
4743            if let Some(text_edit) = completion.text_edit.as_ref() {
4744                let edit = parse_completion_text_edit(text_edit, &buffer_snapshot);
4745
4746                if let Some((old_range, mut text_edit_new_text)) = edit {
4747                    LineEnding::normalize(&mut text_edit_new_text);
4748
4749                    new_text = text_edit_new_text;
4750                    old_start = Some(serialize_anchor(&old_range.start));
4751                    old_end = Some(serialize_anchor(&old_range.end));
4752                }
4753            }
4754        }
4755
4756        Ok(proto::ResolveCompletionDocumentationResponse {
4757            documentation,
4758            documentation_is_markdown,
4759            old_start,
4760            old_end,
4761            new_text,
4762            lsp_completion,
4763        })
4764    }
4765
4766    async fn handle_on_type_formatting(
4767        this: Model<Self>,
4768        envelope: TypedEnvelope<proto::OnTypeFormatting>,
4769        mut cx: AsyncAppContext,
4770    ) -> Result<proto::OnTypeFormattingResponse> {
4771        let on_type_formatting = this.update(&mut cx, |this, cx| {
4772            let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
4773            let buffer = this.buffer_store.read(cx).get_existing(buffer_id)?;
4774            let position = envelope
4775                .payload
4776                .position
4777                .and_then(deserialize_anchor)
4778                .ok_or_else(|| anyhow!("invalid position"))?;
4779            Ok::<_, anyhow::Error>(this.apply_on_type_formatting(
4780                buffer,
4781                position,
4782                envelope.payload.trigger.clone(),
4783                cx,
4784            ))
4785        })??;
4786
4787        let transaction = on_type_formatting
4788            .await?
4789            .as_ref()
4790            .map(language::proto::serialize_transaction);
4791        Ok(proto::OnTypeFormattingResponse { transaction })
4792    }
4793
4794    async fn handle_refresh_inlay_hints(
4795        this: Model<Self>,
4796        _: TypedEnvelope<proto::RefreshInlayHints>,
4797        mut cx: AsyncAppContext,
4798    ) -> Result<proto::Ack> {
4799        this.update(&mut cx, |_, cx| {
4800            cx.emit(LspStoreEvent::RefreshInlayHints);
4801        })?;
4802        Ok(proto::Ack {})
4803    }
4804
4805    async fn handle_inlay_hints(
4806        this: Model<Self>,
4807        envelope: TypedEnvelope<proto::InlayHints>,
4808        mut cx: AsyncAppContext,
4809    ) -> Result<proto::InlayHintsResponse> {
4810        let sender_id = envelope.original_sender_id().unwrap_or_default();
4811        let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
4812        let buffer = this.update(&mut cx, |this, cx| {
4813            this.buffer_store.read(cx).get_existing(buffer_id)
4814        })??;
4815        buffer
4816            .update(&mut cx, |buffer, _| {
4817                buffer.wait_for_version(deserialize_version(&envelope.payload.version))
4818            })?
4819            .await
4820            .with_context(|| format!("waiting for version for buffer {}", buffer.entity_id()))?;
4821
4822        let start = envelope
4823            .payload
4824            .start
4825            .and_then(deserialize_anchor)
4826            .context("missing range start")?;
4827        let end = envelope
4828            .payload
4829            .end
4830            .and_then(deserialize_anchor)
4831            .context("missing range end")?;
4832        let buffer_hints = this
4833            .update(&mut cx, |lsp_store, cx| {
4834                lsp_store.inlay_hints(buffer.clone(), start..end, cx)
4835            })?
4836            .await
4837            .context("inlay hints fetch")?;
4838
4839        this.update(&mut cx, |project, cx| {
4840            InlayHints::response_to_proto(
4841                buffer_hints,
4842                project,
4843                sender_id,
4844                &buffer.read(cx).version(),
4845                cx,
4846            )
4847        })
4848    }
4849
4850    async fn handle_resolve_inlay_hint(
4851        this: Model<Self>,
4852        envelope: TypedEnvelope<proto::ResolveInlayHint>,
4853        mut cx: AsyncAppContext,
4854    ) -> Result<proto::ResolveInlayHintResponse> {
4855        let proto_hint = envelope
4856            .payload
4857            .hint
4858            .expect("incorrect protobuf resolve inlay hint message: missing the inlay hint");
4859        let hint = InlayHints::proto_to_project_hint(proto_hint)
4860            .context("resolved proto inlay hint conversion")?;
4861        let buffer = this.update(&mut cx, |this, cx| {
4862            let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
4863            this.buffer_store.read(cx).get_existing(buffer_id)
4864        })??;
4865        let response_hint = this
4866            .update(&mut cx, |this, cx| {
4867                this.resolve_inlay_hint(
4868                    hint,
4869                    buffer,
4870                    LanguageServerId(envelope.payload.language_server_id as usize),
4871                    cx,
4872                )
4873            })?
4874            .await
4875            .context("inlay hints fetch")?;
4876        Ok(proto::ResolveInlayHintResponse {
4877            hint: Some(InlayHints::project_to_proto_hint(response_hint)),
4878        })
4879    }
4880
4881    async fn handle_open_buffer_for_symbol(
4882        this: Model<Self>,
4883        envelope: TypedEnvelope<proto::OpenBufferForSymbol>,
4884        mut cx: AsyncAppContext,
4885    ) -> Result<proto::OpenBufferForSymbolResponse> {
4886        let peer_id = envelope.original_sender_id().unwrap_or_default();
4887        let symbol = envelope
4888            .payload
4889            .symbol
4890            .ok_or_else(|| anyhow!("invalid symbol"))?;
4891        let symbol = Self::deserialize_symbol(symbol)?;
4892        let symbol = this.update(&mut cx, |this, _| {
4893            let signature = this.symbol_signature(&symbol.path);
4894            if signature == symbol.signature {
4895                Ok(symbol)
4896            } else {
4897                Err(anyhow!("invalid symbol signature"))
4898            }
4899        })??;
4900        let buffer = this
4901            .update(&mut cx, |this, cx| {
4902                this.open_buffer_for_symbol(
4903                    &Symbol {
4904                        language_server_name: symbol.language_server_name,
4905                        source_worktree_id: symbol.source_worktree_id,
4906                        path: symbol.path,
4907                        name: symbol.name,
4908                        kind: symbol.kind,
4909                        range: symbol.range,
4910                        signature: symbol.signature,
4911                        label: CodeLabel {
4912                            text: Default::default(),
4913                            runs: Default::default(),
4914                            filter_range: Default::default(),
4915                        },
4916                    },
4917                    cx,
4918                )
4919            })?
4920            .await?;
4921
4922        this.update(&mut cx, |this, cx| {
4923            let is_private = buffer
4924                .read(cx)
4925                .file()
4926                .map(|f| f.is_private())
4927                .unwrap_or_default();
4928            if is_private {
4929                Err(anyhow!(rpc::ErrorCode::UnsharedItem))
4930            } else {
4931                this.buffer_store
4932                    .update(cx, |buffer_store, cx| {
4933                        buffer_store.create_buffer_for_peer(&buffer, peer_id, cx)
4934                    })
4935                    .detach_and_log_err(cx);
4936                let buffer_id = buffer.read(cx).remote_id().to_proto();
4937                Ok(proto::OpenBufferForSymbolResponse { buffer_id })
4938            }
4939        })?
4940    }
4941
4942    fn symbol_signature(&self, project_path: &ProjectPath) -> [u8; 32] {
4943        let mut hasher = Sha256::new();
4944        hasher.update(project_path.worktree_id.to_proto().to_be_bytes());
4945        hasher.update(project_path.path.to_string_lossy().as_bytes());
4946        hasher.update(self.nonce.to_be_bytes());
4947        hasher.finalize().as_slice().try_into().unwrap()
4948    }
4949
4950    pub async fn handle_get_project_symbols(
4951        this: Model<Self>,
4952        envelope: TypedEnvelope<proto::GetProjectSymbols>,
4953        mut cx: AsyncAppContext,
4954    ) -> Result<proto::GetProjectSymbolsResponse> {
4955        let symbols = this
4956            .update(&mut cx, |this, cx| {
4957                this.symbols(&envelope.payload.query, cx)
4958            })?
4959            .await?;
4960
4961        Ok(proto::GetProjectSymbolsResponse {
4962            symbols: symbols.iter().map(Self::serialize_symbol).collect(),
4963        })
4964    }
4965
4966    pub async fn handle_restart_language_servers(
4967        this: Model<Self>,
4968        envelope: TypedEnvelope<proto::RestartLanguageServers>,
4969        mut cx: AsyncAppContext,
4970    ) -> Result<proto::Ack> {
4971        this.update(&mut cx, |this, cx| {
4972            let buffers: Vec<_> = envelope
4973                .payload
4974                .buffer_ids
4975                .into_iter()
4976                .flat_map(|buffer_id| {
4977                    this.buffer_store
4978                        .read(cx)
4979                        .get(BufferId::new(buffer_id).log_err()?)
4980                })
4981                .collect();
4982            this.restart_language_servers_for_buffers(buffers, cx)
4983        })?;
4984
4985        Ok(proto::Ack {})
4986    }
4987
4988    async fn handle_apply_additional_edits_for_completion(
4989        this: Model<Self>,
4990        envelope: TypedEnvelope<proto::ApplyCompletionAdditionalEdits>,
4991        mut cx: AsyncAppContext,
4992    ) -> Result<proto::ApplyCompletionAdditionalEditsResponse> {
4993        let (buffer, completion) = this.update(&mut cx, |this, cx| {
4994            let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
4995            let buffer = this.buffer_store.read(cx).get_existing(buffer_id)?;
4996            let completion = Self::deserialize_completion(
4997                envelope
4998                    .payload
4999                    .completion
5000                    .ok_or_else(|| anyhow!("invalid completion"))?,
5001            )?;
5002            anyhow::Ok((buffer, completion))
5003        })??;
5004
5005        let apply_additional_edits = this.update(&mut cx, |this, cx| {
5006            this.apply_additional_edits_for_completion(
5007                buffer,
5008                Completion {
5009                    old_range: completion.old_range,
5010                    new_text: completion.new_text,
5011                    lsp_completion: completion.lsp_completion,
5012                    server_id: completion.server_id,
5013                    documentation: None,
5014                    label: CodeLabel {
5015                        text: Default::default(),
5016                        runs: Default::default(),
5017                        filter_range: Default::default(),
5018                    },
5019                    confirm: None,
5020                },
5021                false,
5022                cx,
5023            )
5024        })?;
5025
5026        Ok(proto::ApplyCompletionAdditionalEditsResponse {
5027            transaction: apply_additional_edits
5028                .await?
5029                .as_ref()
5030                .map(language::proto::serialize_transaction),
5031        })
5032    }
5033    pub fn last_formatting_failure(&self) -> Option<&str> {
5034        self.as_local()
5035            .and_then(|local| local.last_formatting_failure.as_deref())
5036    }
5037
5038    pub fn environment_for_buffer(
5039        &self,
5040        buffer: &Model<Buffer>,
5041        cx: &mut ModelContext<Self>,
5042    ) -> Shared<Task<Option<HashMap<String, String>>>> {
5043        let worktree_id = buffer.read(cx).file().map(|file| file.worktree_id(cx));
5044        let worktree_abs_path = worktree_id.and_then(|worktree_id| {
5045            self.worktree_store
5046                .read(cx)
5047                .worktree_for_id(worktree_id, cx)
5048                .map(|entry| entry.read(cx).abs_path().clone())
5049        });
5050
5051        if let Some(environment) = &self.as_local().map(|local| local.environment.clone()) {
5052            environment.update(cx, |env, cx| {
5053                env.get_environment(worktree_id, worktree_abs_path, cx)
5054            })
5055        } else {
5056            Task::ready(None).shared()
5057        }
5058    }
5059
5060    pub fn format(
5061        &mut self,
5062        buffers: HashSet<Model<Buffer>>,
5063        push_to_history: bool,
5064        trigger: FormatTrigger,
5065        cx: &mut ModelContext<Self>,
5066    ) -> Task<anyhow::Result<ProjectTransaction>> {
5067        if let Some(_) = self.as_local() {
5068            let buffers_with_paths = buffers
5069                .into_iter()
5070                .map(|buffer_handle| {
5071                    let buffer = buffer_handle.read(cx);
5072                    let buffer_abs_path = File::from_dyn(buffer.file())
5073                        .and_then(|file| file.as_local().map(|f| f.abs_path(cx)));
5074
5075                    (buffer_handle, buffer_abs_path)
5076                })
5077                .collect::<Vec<_>>();
5078
5079            cx.spawn(move |lsp_store, mut cx| async move {
5080                let mut formattable_buffers = Vec::with_capacity(buffers_with_paths.len());
5081
5082                for (handle, abs_path) in buffers_with_paths {
5083                    let env = lsp_store
5084                        .update(&mut cx, |lsp_store, cx| {
5085                            lsp_store.environment_for_buffer(&handle, cx)
5086                        })?
5087                        .await;
5088
5089                    formattable_buffers.push(FormattableBuffer {
5090                        handle,
5091                        abs_path,
5092                        env,
5093                    });
5094                }
5095
5096                let result = LocalLspStore::format_locally(
5097                    lsp_store.clone(),
5098                    formattable_buffers,
5099                    push_to_history,
5100                    trigger,
5101                    cx.clone(),
5102                )
5103                .await;
5104
5105                lsp_store.update(&mut cx, |lsp_store, _| {
5106                    let local = lsp_store.as_local_mut().unwrap();
5107                    match &result {
5108                        Ok(_) => local.last_formatting_failure = None,
5109                        Err(error) => {
5110                            local.last_formatting_failure.replace(error.to_string());
5111                        }
5112                    }
5113                })?;
5114
5115                result
5116            })
5117        } else if let Some((client, project_id)) = self.upstream_client() {
5118            let buffer_store = self.buffer_store();
5119            cx.spawn(move |_, mut cx| async move {
5120                let response = client
5121                    .request(proto::FormatBuffers {
5122                        project_id,
5123                        trigger: trigger as i32,
5124                        buffer_ids: buffers
5125                            .iter()
5126                            .map(|buffer| {
5127                                buffer.update(&mut cx, |buffer, _| buffer.remote_id().into())
5128                            })
5129                            .collect::<Result<_>>()?,
5130                    })
5131                    .await?
5132                    .transaction
5133                    .ok_or_else(|| anyhow!("missing transaction"))?;
5134
5135                buffer_store
5136                    .update(&mut cx, |buffer_store, cx| {
5137                        buffer_store.deserialize_project_transaction(response, push_to_history, cx)
5138                    })?
5139                    .await
5140            })
5141        } else {
5142            Task::ready(Ok(ProjectTransaction::default()))
5143        }
5144    }
5145
5146    async fn handle_format_buffers(
5147        this: Model<Self>,
5148        envelope: TypedEnvelope<proto::FormatBuffers>,
5149        mut cx: AsyncAppContext,
5150    ) -> Result<proto::FormatBuffersResponse> {
5151        let sender_id = envelope.original_sender_id().unwrap_or_default();
5152        let format = this.update(&mut cx, |this, cx| {
5153            let mut buffers = HashSet::default();
5154            for buffer_id in &envelope.payload.buffer_ids {
5155                let buffer_id = BufferId::new(*buffer_id)?;
5156                buffers.insert(this.buffer_store.read(cx).get_existing(buffer_id)?);
5157            }
5158            let trigger = FormatTrigger::from_proto(envelope.payload.trigger);
5159            Ok::<_, anyhow::Error>(this.format(buffers, false, trigger, cx))
5160        })??;
5161
5162        let project_transaction = format.await?;
5163        let project_transaction = this.update(&mut cx, |this, cx| {
5164            this.buffer_store.update(cx, |buffer_store, cx| {
5165                buffer_store.serialize_project_transaction_for_peer(
5166                    project_transaction,
5167                    sender_id,
5168                    cx,
5169                )
5170            })
5171        })?;
5172        Ok(proto::FormatBuffersResponse {
5173            transaction: Some(project_transaction),
5174        })
5175    }
5176
5177    fn language_settings<'a>(
5178        &'a self,
5179        worktree: &'a Model<Worktree>,
5180        language: &LanguageName,
5181        cx: &'a mut ModelContext<Self>,
5182    ) -> &'a LanguageSettings {
5183        let root_file = worktree.update(cx, |tree, cx| tree.root_file(cx));
5184        all_language_settings(root_file.map(|f| f as _).as_ref(), cx).language(Some(language))
5185    }
5186
5187    pub fn start_language_servers(
5188        &mut self,
5189        worktree: &Model<Worktree>,
5190        language: LanguageName,
5191        cx: &mut ModelContext<Self>,
5192    ) {
5193        let settings = self.language_settings(worktree, &language, cx);
5194        if !settings.enable_language_server || self.mode.is_remote() {
5195            return;
5196        }
5197
5198        let available_lsp_adapters = self.languages.clone().lsp_adapters(&language);
5199        let available_language_servers = available_lsp_adapters
5200            .iter()
5201            .map(|lsp_adapter| lsp_adapter.name.clone())
5202            .collect::<Vec<_>>();
5203
5204        let desired_language_servers =
5205            settings.customized_language_servers(&available_language_servers);
5206
5207        let mut enabled_lsp_adapters: Vec<Arc<CachedLspAdapter>> = Vec::new();
5208        for desired_language_server in desired_language_servers {
5209            if let Some(adapter) = available_lsp_adapters
5210                .iter()
5211                .find(|adapter| adapter.name == desired_language_server)
5212            {
5213                enabled_lsp_adapters.push(adapter.clone());
5214                continue;
5215            }
5216
5217            if let Some(adapter) = self
5218                .languages
5219                .load_available_lsp_adapter(&desired_language_server)
5220            {
5221                self.languages
5222                    .register_lsp_adapter(language.clone(), adapter.adapter.clone());
5223                enabled_lsp_adapters.push(adapter);
5224                continue;
5225            }
5226
5227            log::warn!(
5228                "no language server found matching '{}'",
5229                desired_language_server.0
5230            );
5231        }
5232
5233        for adapter in &enabled_lsp_adapters {
5234            self.start_language_server(worktree, adapter.clone(), language.clone(), cx);
5235        }
5236
5237        // After starting all the language servers, reorder them to reflect the desired order
5238        // based on the settings.
5239        //
5240        // This is done, in part, to ensure that language servers loaded at different points
5241        // (e.g., native vs extension) still end up in the right order at the end, rather than
5242        // it being based on which language server happened to be loaded in first.
5243        self.languages
5244            .reorder_language_servers(&language, enabled_lsp_adapters);
5245    }
5246
5247    fn get_language_server_binary(
5248        &self,
5249        adapter: Arc<CachedLspAdapter>,
5250        delegate: Arc<dyn LspAdapterDelegate>,
5251        allow_binary_download: bool,
5252        cx: &mut ModelContext<Self>,
5253    ) -> Task<Result<LanguageServerBinary>> {
5254        let settings = ProjectSettings::get(
5255            Some(SettingsLocation {
5256                worktree_id: delegate.worktree_id(),
5257                path: Path::new(""),
5258            }),
5259            cx,
5260        )
5261        .lsp
5262        .get(&adapter.name)
5263        .and_then(|s| s.binary.clone());
5264
5265        if settings.as_ref().is_some_and(|b| b.path.is_some()) {
5266            let settings = settings.unwrap();
5267            return cx.spawn(|_, _| async move {
5268                Ok(LanguageServerBinary {
5269                    path: PathBuf::from(&settings.path.unwrap()),
5270                    env: Some(delegate.shell_env().await),
5271                    arguments: settings
5272                        .arguments
5273                        .unwrap_or_default()
5274                        .iter()
5275                        .map(Into::into)
5276                        .collect(),
5277                })
5278            });
5279        }
5280        let lsp_binary_options = LanguageServerBinaryOptions {
5281            allow_path_lookup: !settings
5282                .as_ref()
5283                .and_then(|b| b.ignore_system_version)
5284                .unwrap_or_default(),
5285            allow_binary_download,
5286        };
5287        cx.spawn(|_, mut cx| async move {
5288            let binary_result = adapter
5289                .clone()
5290                .get_language_server_command(delegate.clone(), lsp_binary_options, &mut cx)
5291                .await;
5292
5293            delegate.update_status(adapter.name.clone(), LanguageServerBinaryStatus::None);
5294
5295            let mut binary = binary_result?;
5296            if let Some(arguments) = settings.and_then(|b| b.arguments) {
5297                binary.arguments = arguments.into_iter().map(Into::into).collect();
5298            }
5299
5300            // If we do have a project environment (either by spawning a shell in in the project directory
5301            // or by getting it from the CLI) and the language server command itself
5302            // doesn't have an environment, then we use the project environment.
5303            if binary.env.is_none() {
5304                log::info!(
5305                    "using project environment for language server {:?}",
5306                    adapter.name()
5307                );
5308                binary.env = Some(delegate.shell_env().await);
5309            }
5310            Ok(binary)
5311        })
5312    }
5313
5314    fn start_language_server(
5315        &mut self,
5316        worktree_handle: &Model<Worktree>,
5317        adapter: Arc<CachedLspAdapter>,
5318        language: LanguageName,
5319        cx: &mut ModelContext<Self>,
5320    ) {
5321        if self.mode.is_remote() {
5322            return;
5323        }
5324
5325        let worktree = worktree_handle.read(cx);
5326        let worktree_id = worktree.id();
5327        let worktree_path = worktree.abs_path();
5328        let key = (worktree_id, adapter.name.clone());
5329
5330        if self.language_server_ids.contains_key(&key) {
5331            return;
5332        }
5333
5334        let project_settings = ProjectSettings::get(
5335            Some(SettingsLocation {
5336                worktree_id,
5337                path: Path::new(""),
5338            }),
5339            cx,
5340        );
5341        let lsp = project_settings.lsp.get(&adapter.name);
5342        let override_options = lsp.and_then(|s| s.initialization_options.clone());
5343
5344        let stderr_capture = Arc::new(Mutex::new(Some(String::new())));
5345        let delegate = LocalLspAdapterDelegate::for_local(self, worktree_handle, cx)
5346            as Arc<dyn LspAdapterDelegate>;
5347
5348        let server_id = self.languages.next_language_server_id();
5349        let root_path = worktree_path.clone();
5350        log::info!(
5351            "attempting to start language server {:?}, path: {root_path:?}, id: {server_id}",
5352            adapter.name.0
5353        );
5354
5355        let binary = self.get_language_server_binary(adapter.clone(), delegate.clone(), true, cx);
5356
5357        let pending_server = cx.spawn({
5358            let adapter = adapter.clone();
5359            let stderr_capture = stderr_capture.clone();
5360
5361            move |_lsp_store, cx| async move {
5362                let binary = binary.await?;
5363
5364                #[cfg(any(test, feature = "test-support"))]
5365                if let Some(server) = _lsp_store
5366                    .update(&mut cx.clone(), |this, cx| {
5367                        this.languages.create_fake_language_server(
5368                            server_id,
5369                            &adapter.name,
5370                            binary.clone(),
5371                            cx.to_async(),
5372                        )
5373                    })
5374                    .ok()
5375                    .flatten()
5376                {
5377                    return Ok(server);
5378                }
5379
5380                lsp::LanguageServer::new(
5381                    stderr_capture,
5382                    server_id,
5383                    binary,
5384                    &root_path,
5385                    adapter.code_action_kinds(),
5386                    cx,
5387                )
5388            }
5389        });
5390
5391        let state = LanguageServerState::Starting({
5392            let server_name = adapter.name.0.clone();
5393            let delegate = delegate as Arc<dyn LspAdapterDelegate>;
5394            let language = language.clone();
5395            let key = key.clone();
5396            let adapter = adapter.clone();
5397
5398            cx.spawn(move |this, mut cx| async move {
5399                let result = {
5400                    let delegate = delegate.clone();
5401                    let adapter = adapter.clone();
5402                    let this = this.clone();
5403                    let mut cx = cx.clone();
5404                    async move {
5405                        let language_server = pending_server.await?;
5406
5407                        let workspace_config = adapter
5408                            .adapter
5409                            .clone()
5410                            .workspace_configuration(&delegate, &mut cx)
5411                            .await?;
5412
5413                        let mut initialization_options = adapter
5414                            .adapter
5415                            .clone()
5416                            .initialization_options(&(delegate))
5417                            .await?;
5418
5419                        Self::setup_lsp_messages(this.clone(), &language_server, delegate, adapter);
5420
5421                        match (&mut initialization_options, override_options) {
5422                            (Some(initialization_options), Some(override_options)) => {
5423                                merge_json_value_into(override_options, initialization_options);
5424                            }
5425                            (None, override_options) => initialization_options = override_options,
5426                            _ => {}
5427                        }
5428
5429                        let language_server = cx
5430                            .update(|cx| language_server.initialize(initialization_options, cx))?
5431                            .await
5432                            .inspect_err(|_| {
5433                                if let Some(this) = this.upgrade() {
5434                                    this.update(&mut cx, |_, cx| {
5435                                        cx.emit(LspStoreEvent::LanguageServerRemoved(server_id))
5436                                    })
5437                                    .ok();
5438                                }
5439                            })?;
5440
5441                        language_server
5442                            .notify::<lsp::notification::DidChangeConfiguration>(
5443                                lsp::DidChangeConfigurationParams {
5444                                    settings: workspace_config,
5445                                },
5446                            )
5447                            .ok();
5448
5449                        anyhow::Ok(language_server)
5450                    }
5451                }
5452                .await;
5453
5454                match result {
5455                    Ok(server) => {
5456                        this.update(&mut cx, |this, mut cx| {
5457                            this.insert_newly_running_language_server(
5458                                language,
5459                                adapter,
5460                                server.clone(),
5461                                server_id,
5462                                key,
5463                                &mut cx,
5464                            );
5465                        })
5466                        .ok();
5467                        stderr_capture.lock().take();
5468                        Some(server)
5469                    }
5470
5471                    Err(err) => {
5472                        let log = stderr_capture.lock().take().unwrap_or_default();
5473                        delegate.update_status(
5474                            adapter.name(),
5475                            LanguageServerBinaryStatus::Failed {
5476                                error: format!("{err}\n-- stderr--\n{}", log),
5477                            },
5478                        );
5479                        log::error!("Failed to start language server {server_name:?}: {err}");
5480                        log::error!("server stderr: {:?}", log);
5481                        None
5482                    }
5483                }
5484            })
5485        });
5486
5487        self.as_local_mut()
5488            .unwrap()
5489            .language_servers
5490            .insert(server_id, state);
5491        self.language_server_ids.insert(key, server_id);
5492    }
5493
5494    async fn shutdown_language_server(
5495        server_state: Option<LanguageServerState>,
5496        name: LanguageServerName,
5497        cx: AsyncAppContext,
5498    ) {
5499        let server = match server_state {
5500            Some(LanguageServerState::Starting(task)) => {
5501                let mut timer = cx
5502                    .background_executor()
5503                    .timer(SERVER_LAUNCHING_BEFORE_SHUTDOWN_TIMEOUT)
5504                    .fuse();
5505
5506                select! {
5507                    server = task.fuse() => server,
5508                    _ = timer => {
5509                        log::info!(
5510                            "timeout waiting for language server {} to finish launching before stopping",
5511                            name
5512                        );
5513                        None
5514                    },
5515                }
5516            }
5517
5518            Some(LanguageServerState::Running { server, .. }) => Some(server),
5519
5520            None => None,
5521        };
5522
5523        if let Some(server) = server {
5524            if let Some(shutdown) = server.shutdown() {
5525                shutdown.await;
5526            }
5527        }
5528    }
5529
5530    // Returns a list of all of the worktrees which no longer have a language server and the root path
5531    // for the stopped server
5532    fn stop_local_language_server(
5533        &mut self,
5534        worktree_id: WorktreeId,
5535        adapter_name: LanguageServerName,
5536        cx: &mut ModelContext<Self>,
5537    ) -> Task<Vec<WorktreeId>> {
5538        let key = (worktree_id, adapter_name);
5539        if self.mode.is_local() {
5540            if let Some(server_id) = self.language_server_ids.remove(&key) {
5541                let name = key.1;
5542                log::info!("stopping language server {name}");
5543
5544                // Remove other entries for this language server as well
5545                let mut orphaned_worktrees = vec![worktree_id];
5546                let other_keys = self.language_server_ids.keys().cloned().collect::<Vec<_>>();
5547                for other_key in other_keys {
5548                    if self.language_server_ids.get(&other_key) == Some(&server_id) {
5549                        self.language_server_ids.remove(&other_key);
5550                        orphaned_worktrees.push(other_key.0);
5551                    }
5552                }
5553
5554                self.buffer_store.update(cx, |buffer_store, cx| {
5555                    for buffer in buffer_store.buffers() {
5556                        buffer.update(cx, |buffer, cx| {
5557                            buffer.update_diagnostics(
5558                                server_id,
5559                                DiagnosticSet::new([], buffer),
5560                                cx,
5561                            );
5562                        });
5563                    }
5564                });
5565
5566                for (worktree_id, summaries) in self.diagnostic_summaries.iter_mut() {
5567                    summaries.retain(|path, summaries_by_server_id| {
5568                        if summaries_by_server_id.remove(&server_id).is_some() {
5569                            if let Some((client, project_id)) = self.downstream_client.clone() {
5570                                client
5571                                    .send(proto::UpdateDiagnosticSummary {
5572                                        project_id,
5573                                        worktree_id: worktree_id.to_proto(),
5574                                        summary: Some(proto::DiagnosticSummary {
5575                                            path: path.to_string_lossy().to_string(),
5576                                            language_server_id: server_id.0 as u64,
5577                                            error_count: 0,
5578                                            warning_count: 0,
5579                                        }),
5580                                    })
5581                                    .log_err();
5582                            }
5583                            !summaries_by_server_id.is_empty()
5584                        } else {
5585                            true
5586                        }
5587                    });
5588                }
5589
5590                for diagnostics in self.diagnostics.values_mut() {
5591                    diagnostics.retain(|_, diagnostics_by_server_id| {
5592                        if let Ok(ix) =
5593                            diagnostics_by_server_id.binary_search_by_key(&server_id, |e| e.0)
5594                        {
5595                            diagnostics_by_server_id.remove(ix);
5596                            !diagnostics_by_server_id.is_empty()
5597                        } else {
5598                            true
5599                        }
5600                    });
5601                }
5602
5603                self.as_local_mut()
5604                    .unwrap()
5605                    .language_server_watched_paths
5606                    .remove(&server_id);
5607                self.language_server_statuses.remove(&server_id);
5608                cx.notify();
5609
5610                let server_state = self
5611                    .as_local_mut()
5612                    .unwrap()
5613                    .language_servers
5614                    .remove(&server_id);
5615                cx.emit(LspStoreEvent::LanguageServerRemoved(server_id));
5616                cx.spawn(move |_, cx| async move {
5617                    Self::shutdown_language_server(server_state, name, cx).await;
5618                    orphaned_worktrees
5619                })
5620            } else {
5621                Task::ready(Vec::new())
5622            }
5623        } else {
5624            Task::ready(Vec::new())
5625        }
5626    }
5627
5628    pub fn restart_language_servers_for_buffers(
5629        &mut self,
5630        buffers: impl IntoIterator<Item = Model<Buffer>>,
5631        cx: &mut ModelContext<Self>,
5632    ) {
5633        if let Some((client, project_id)) = self.upstream_client() {
5634            let request = client.request(proto::RestartLanguageServers {
5635                project_id,
5636                buffer_ids: buffers
5637                    .into_iter()
5638                    .map(|b| b.read(cx).remote_id().to_proto())
5639                    .collect(),
5640            });
5641            cx.background_executor()
5642                .spawn(request)
5643                .detach_and_log_err(cx);
5644        } else {
5645            let language_server_lookup_info: HashSet<(Model<Worktree>, LanguageName)> = buffers
5646                .into_iter()
5647                .filter_map(|buffer| {
5648                    let buffer = buffer.read(cx);
5649                    let file = buffer.file()?;
5650                    let worktree = File::from_dyn(Some(file))?.worktree.clone();
5651                    let language =
5652                        self.languages
5653                            .language_for_file(file, Some(buffer.as_rope()), cx)?;
5654
5655                    Some((worktree, language.name()))
5656                })
5657                .collect();
5658
5659            for (worktree, language) in language_server_lookup_info {
5660                self.restart_local_language_servers(worktree, language, cx);
5661            }
5662        }
5663    }
5664
5665    fn restart_local_language_servers(
5666        &mut self,
5667        worktree: Model<Worktree>,
5668        language: LanguageName,
5669        cx: &mut ModelContext<Self>,
5670    ) {
5671        let worktree_id = worktree.read(cx).id();
5672
5673        let stop_tasks = self
5674            .languages
5675            .clone()
5676            .lsp_adapters(&language)
5677            .iter()
5678            .map(|adapter| {
5679                let stop_task =
5680                    self.stop_local_language_server(worktree_id, adapter.name.clone(), cx);
5681                (stop_task, adapter.name.clone())
5682            })
5683            .collect::<Vec<_>>();
5684        if stop_tasks.is_empty() {
5685            return;
5686        }
5687
5688        cx.spawn(move |this, mut cx| async move {
5689            // For each stopped language server, record all of the worktrees with which
5690            // it was associated.
5691            let mut affected_worktrees = Vec::new();
5692            for (stop_task, language_server_name) in stop_tasks {
5693                for affected_worktree_id in stop_task.await {
5694                    affected_worktrees.push((affected_worktree_id, language_server_name.clone()));
5695                }
5696            }
5697
5698            this.update(&mut cx, |this, cx| {
5699                // Restart the language server for the given worktree.
5700                this.start_language_servers(&worktree, language.clone(), cx);
5701
5702                // Lookup new server ids and set them for each of the orphaned worktrees
5703                for (affected_worktree_id, language_server_name) in affected_worktrees {
5704                    if let Some(new_server_id) = this
5705                        .language_server_ids
5706                        .get(&(worktree_id, language_server_name.clone()))
5707                        .cloned()
5708                    {
5709                        this.language_server_ids
5710                            .insert((affected_worktree_id, language_server_name), new_server_id);
5711                    }
5712                }
5713            })
5714            .ok();
5715        })
5716        .detach();
5717    }
5718
5719    fn setup_lsp_messages(
5720        this: WeakModel<Self>,
5721        language_server: &LanguageServer,
5722        delegate: Arc<dyn LspAdapterDelegate>,
5723        adapter: Arc<CachedLspAdapter>,
5724    ) {
5725        let name = language_server.name();
5726        let server_id = language_server.server_id();
5727        language_server
5728            .on_notification::<lsp::notification::PublishDiagnostics, _>({
5729                let adapter = adapter.clone();
5730                let this = this.clone();
5731                move |mut params, mut cx| {
5732                    let adapter = adapter.clone();
5733                    if let Some(this) = this.upgrade() {
5734                        adapter.process_diagnostics(&mut params);
5735                        // Everything else has to be on the server, Can we make it on the client?
5736                        this.update(&mut cx, |this, cx| {
5737                            this.update_diagnostics(
5738                                server_id,
5739                                params,
5740                                &adapter.disk_based_diagnostic_sources,
5741                                cx,
5742                            )
5743                            .log_err();
5744                        })
5745                        .ok();
5746                    }
5747                }
5748            })
5749            .detach();
5750
5751        language_server
5752            .on_request::<lsp::request::WorkspaceConfiguration, _, _>({
5753                let adapter = adapter.adapter.clone();
5754                let delegate = delegate.clone();
5755                move |params, mut cx| {
5756                    let adapter = adapter.clone();
5757                    let delegate = delegate.clone();
5758                    async move {
5759                        let workspace_config =
5760                            adapter.workspace_configuration(&delegate, &mut cx).await?;
5761                        Ok(params
5762                            .items
5763                            .into_iter()
5764                            .map(|item| {
5765                                if let Some(section) = &item.section {
5766                                    workspace_config
5767                                        .get(section)
5768                                        .cloned()
5769                                        .unwrap_or(serde_json::Value::Null)
5770                                } else {
5771                                    workspace_config.clone()
5772                                }
5773                            })
5774                            .collect())
5775                    }
5776                }
5777            })
5778            .detach();
5779
5780        language_server
5781            .on_request::<lsp::request::WorkspaceFoldersRequest, _, _>({
5782                let this = this.clone();
5783                move |_, mut cx| {
5784                    let this = this.clone();
5785                    async move {
5786                        let Some(server) =
5787                            this.update(&mut cx, |this, _| this.language_server_for_id(server_id))?
5788                        else {
5789                            return Ok(None);
5790                        };
5791                        let root = server.root_path();
5792                        let Ok(uri) = Url::from_file_path(&root) else {
5793                            return Ok(None);
5794                        };
5795                        Ok(Some(vec![WorkspaceFolder {
5796                            uri,
5797                            name: Default::default(),
5798                        }]))
5799                    }
5800                }
5801            })
5802            .detach();
5803        // Even though we don't have handling for these requests, respond to them to
5804        // avoid stalling any language server like `gopls` which waits for a response
5805        // to these requests when initializing.
5806        language_server
5807            .on_request::<lsp::request::WorkDoneProgressCreate, _, _>({
5808                let this = this.clone();
5809                move |params, mut cx| {
5810                    let this = this.clone();
5811                    async move {
5812                        this.update(&mut cx, |this, _| {
5813                            if let Some(status) = this.language_server_statuses.get_mut(&server_id)
5814                            {
5815                                if let lsp::NumberOrString::String(token) = params.token {
5816                                    status.progress_tokens.insert(token);
5817                                }
5818                            }
5819                        })?;
5820
5821                        Ok(())
5822                    }
5823                }
5824            })
5825            .detach();
5826
5827        language_server
5828            .on_request::<lsp::request::RegisterCapability, _, _>({
5829                let this = this.clone();
5830                move |params, mut cx| {
5831                    let this = this.clone();
5832                    async move {
5833                        for reg in params.registrations {
5834                            match reg.method.as_str() {
5835                                "workspace/didChangeWatchedFiles" => {
5836                                    if let Some(options) = reg.register_options {
5837                                        let options = serde_json::from_value(options)?;
5838                                        this.update(&mut cx, |this, cx| {
5839                                            this.on_lsp_did_change_watched_files(
5840                                                server_id, &reg.id, options, cx,
5841                                            );
5842                                        })?;
5843                                    }
5844                                }
5845                                "textDocument/rangeFormatting" => {
5846                                    this.update(&mut cx, |this, _| {
5847                                        if let Some(server) = this.language_server_for_id(server_id)
5848                                        {
5849                                            let options = reg
5850                                                .register_options
5851                                                .map(|options| {
5852                                                    serde_json::from_value::<
5853                                                        lsp::DocumentRangeFormattingOptions,
5854                                                    >(
5855                                                        options
5856                                                    )
5857                                                })
5858                                                .transpose()?;
5859                                            let provider = match options {
5860                                                None => OneOf::Left(true),
5861                                                Some(options) => OneOf::Right(options),
5862                                            };
5863                                            server.update_capabilities(|capabilities| {
5864                                                capabilities.document_range_formatting_provider =
5865                                                    Some(provider);
5866                                            })
5867                                        }
5868                                        anyhow::Ok(())
5869                                    })??;
5870                                }
5871                                "textDocument/onTypeFormatting" => {
5872                                    this.update(&mut cx, |this, _| {
5873                                        if let Some(server) = this.language_server_for_id(server_id)
5874                                        {
5875                                            let options = reg
5876                                                .register_options
5877                                                .map(|options| {
5878                                                    serde_json::from_value::<
5879                                                        lsp::DocumentOnTypeFormattingOptions,
5880                                                    >(
5881                                                        options
5882                                                    )
5883                                                })
5884                                                .transpose()?;
5885                                            if let Some(options) = options {
5886                                                server.update_capabilities(|capabilities| {
5887                                                    capabilities
5888                                                        .document_on_type_formatting_provider =
5889                                                        Some(options);
5890                                                })
5891                                            }
5892                                        }
5893                                        anyhow::Ok(())
5894                                    })??;
5895                                }
5896                                "textDocument/formatting" => {
5897                                    this.update(&mut cx, |this, _| {
5898                                        if let Some(server) = this.language_server_for_id(server_id)
5899                                        {
5900                                            let options = reg
5901                                                .register_options
5902                                                .map(|options| {
5903                                                    serde_json::from_value::<
5904                                                        lsp::DocumentFormattingOptions,
5905                                                    >(
5906                                                        options
5907                                                    )
5908                                                })
5909                                                .transpose()?;
5910                                            let provider = match options {
5911                                                None => OneOf::Left(true),
5912                                                Some(options) => OneOf::Right(options),
5913                                            };
5914                                            server.update_capabilities(|capabilities| {
5915                                                capabilities.document_formatting_provider =
5916                                                    Some(provider);
5917                                            })
5918                                        }
5919                                        anyhow::Ok(())
5920                                    })??;
5921                                }
5922                                _ => log::warn!("unhandled capability registration: {reg:?}"),
5923                            }
5924                        }
5925                        Ok(())
5926                    }
5927                }
5928            })
5929            .detach();
5930
5931        language_server
5932            .on_request::<lsp::request::UnregisterCapability, _, _>({
5933                let this = this.clone();
5934                move |params, mut cx| {
5935                    let this = this.clone();
5936                    async move {
5937                        for unreg in params.unregisterations.iter() {
5938                            match unreg.method.as_str() {
5939                                "workspace/didChangeWatchedFiles" => {
5940                                    this.update(&mut cx, |this, cx| {
5941                                        this.on_lsp_unregister_did_change_watched_files(
5942                                            server_id, &unreg.id, cx,
5943                                        );
5944                                    })?;
5945                                }
5946                                "textDocument/rangeFormatting" => {
5947                                    this.update(&mut cx, |this, _| {
5948                                        if let Some(server) = this.language_server_for_id(server_id)
5949                                        {
5950                                            server.update_capabilities(|capabilities| {
5951                                                capabilities.document_range_formatting_provider =
5952                                                    None
5953                                            })
5954                                        }
5955                                    })?;
5956                                }
5957                                "textDocument/onTypeFormatting" => {
5958                                    this.update(&mut cx, |this, _| {
5959                                        if let Some(server) = this.language_server_for_id(server_id)
5960                                        {
5961                                            server.update_capabilities(|capabilities| {
5962                                                capabilities.document_on_type_formatting_provider =
5963                                                    None;
5964                                            })
5965                                        }
5966                                    })?;
5967                                }
5968                                "textDocument/formatting" => {
5969                                    this.update(&mut cx, |this, _| {
5970                                        if let Some(server) = this.language_server_for_id(server_id)
5971                                        {
5972                                            server.update_capabilities(|capabilities| {
5973                                                capabilities.document_formatting_provider = None;
5974                                            })
5975                                        }
5976                                    })?;
5977                                }
5978                                _ => log::warn!("unhandled capability unregistration: {unreg:?}"),
5979                            }
5980                        }
5981                        Ok(())
5982                    }
5983                }
5984            })
5985            .detach();
5986
5987        language_server
5988            .on_request::<lsp::request::ApplyWorkspaceEdit, _, _>({
5989                let adapter = adapter.clone();
5990                let this = this.clone();
5991                move |params, cx| {
5992                    Self::on_lsp_workspace_edit(
5993                        this.clone(),
5994                        params,
5995                        server_id,
5996                        adapter.clone(),
5997                        cx,
5998                    )
5999                }
6000            })
6001            .detach();
6002
6003        language_server
6004            .on_request::<lsp::request::InlayHintRefreshRequest, _, _>({
6005                let this = this.clone();
6006                move |(), mut cx| {
6007                    let this = this.clone();
6008                    async move {
6009                        this.update(&mut cx, |this, cx| {
6010                            cx.emit(LspStoreEvent::RefreshInlayHints);
6011                            this.downstream_client.as_ref().map(|(client, project_id)| {
6012                                client.send(proto::RefreshInlayHints {
6013                                    project_id: *project_id,
6014                                })
6015                            })
6016                        })?
6017                        .transpose()?;
6018                        Ok(())
6019                    }
6020                }
6021            })
6022            .detach();
6023
6024        language_server
6025            .on_request::<lsp::request::ShowMessageRequest, _, _>({
6026                let this = this.clone();
6027                let name = name.to_string();
6028                move |params, mut cx| {
6029                    let this = this.clone();
6030                    let name = name.to_string();
6031                    async move {
6032                        let actions = params.actions.unwrap_or_default();
6033                        let (tx, mut rx) = smol::channel::bounded(1);
6034                        let request = LanguageServerPromptRequest {
6035                            level: match params.typ {
6036                                lsp::MessageType::ERROR => PromptLevel::Critical,
6037                                lsp::MessageType::WARNING => PromptLevel::Warning,
6038                                _ => PromptLevel::Info,
6039                            },
6040                            message: params.message,
6041                            actions,
6042                            response_channel: tx,
6043                            lsp_name: name.clone(),
6044                        };
6045
6046                        let did_update = this
6047                            .update(&mut cx, |_, cx| {
6048                                cx.emit(LspStoreEvent::LanguageServerPrompt(request));
6049                            })
6050                            .is_ok();
6051                        if did_update {
6052                            let response = rx.next().await;
6053
6054                            Ok(response)
6055                        } else {
6056                            Ok(None)
6057                        }
6058                    }
6059                }
6060            })
6061            .detach();
6062
6063        language_server
6064            .on_notification::<ServerStatus, _>({
6065                let this = this.clone();
6066                let name = name.to_string();
6067                move |params, mut cx| {
6068                    let this = this.clone();
6069                    let name = name.to_string();
6070                    if let Some(ref message) = params.message {
6071                        let message = message.trim();
6072                        if !message.is_empty() {
6073                            let formatted_message = format!(
6074                                "Language server {name} (id {server_id}) status update: {message}"
6075                            );
6076                            match params.health {
6077                                ServerHealthStatus::Ok => log::info!("{}", formatted_message),
6078                                ServerHealthStatus::Warning => log::warn!("{}", formatted_message),
6079                                ServerHealthStatus::Error => {
6080                                    log::error!("{}", formatted_message);
6081                                    let (tx, _rx) = smol::channel::bounded(1);
6082                                    let request = LanguageServerPromptRequest {
6083                                        level: PromptLevel::Critical,
6084                                        message: params.message.unwrap_or_default(),
6085                                        actions: Vec::new(),
6086                                        response_channel: tx,
6087                                        lsp_name: name.clone(),
6088                                    };
6089                                    let _ = this
6090                                        .update(&mut cx, |_, cx| {
6091                                            cx.emit(LspStoreEvent::LanguageServerPrompt(request));
6092                                        })
6093                                        .ok();
6094                                }
6095                                ServerHealthStatus::Other(status) => {
6096                                    log::info!(
6097                                        "Unknown server health: {status}\n{formatted_message}"
6098                                    )
6099                                }
6100                            }
6101                        }
6102                    }
6103                }
6104            })
6105            .detach();
6106        language_server
6107            .on_notification::<lsp::notification::ShowMessage, _>({
6108                let this = this.clone();
6109                let name = name.to_string();
6110                move |params, mut cx| {
6111                    let this = this.clone();
6112                    let name = name.to_string();
6113
6114                    let (tx, _) = smol::channel::bounded(1);
6115                    let request = LanguageServerPromptRequest {
6116                        level: match params.typ {
6117                            lsp::MessageType::ERROR => PromptLevel::Critical,
6118                            lsp::MessageType::WARNING => PromptLevel::Warning,
6119                            _ => PromptLevel::Info,
6120                        },
6121                        message: params.message,
6122                        actions: vec![],
6123                        response_channel: tx,
6124                        lsp_name: name.clone(),
6125                    };
6126
6127                    let _ = this.update(&mut cx, |_, cx| {
6128                        cx.emit(LspStoreEvent::LanguageServerPrompt(request));
6129                    });
6130                }
6131            })
6132            .detach();
6133
6134        let disk_based_diagnostics_progress_token =
6135            adapter.disk_based_diagnostics_progress_token.clone();
6136
6137        language_server
6138            .on_notification::<lsp::notification::Progress, _>({
6139                let this = this.clone();
6140                move |params, mut cx| {
6141                    if let Some(this) = this.upgrade() {
6142                        this.update(&mut cx, |this, cx| {
6143                            this.on_lsp_progress(
6144                                params,
6145                                server_id,
6146                                disk_based_diagnostics_progress_token.clone(),
6147                                cx,
6148                            );
6149                        })
6150                        .ok();
6151                    }
6152                }
6153            })
6154            .detach();
6155
6156        language_server
6157            .on_notification::<lsp::notification::LogMessage, _>({
6158                let this = this.clone();
6159                move |params, mut cx| {
6160                    if let Some(this) = this.upgrade() {
6161                        this.update(&mut cx, |_, cx| {
6162                            cx.emit(LspStoreEvent::LanguageServerLog(
6163                                server_id,
6164                                LanguageServerLogType::Log(params.typ),
6165                                params.message,
6166                            ));
6167                        })
6168                        .ok();
6169                    }
6170                }
6171            })
6172            .detach();
6173
6174        language_server
6175            .on_notification::<lsp::notification::LogTrace, _>({
6176                let this = this.clone();
6177                move |params, mut cx| {
6178                    if let Some(this) = this.upgrade() {
6179                        this.update(&mut cx, |_, cx| {
6180                            cx.emit(LspStoreEvent::LanguageServerLog(
6181                                server_id,
6182                                LanguageServerLogType::Trace(params.verbose),
6183                                params.message,
6184                            ));
6185                        })
6186                        .ok();
6187                    }
6188                }
6189            })
6190            .detach();
6191    }
6192
6193    pub fn update_diagnostics(
6194        &mut self,
6195        language_server_id: LanguageServerId,
6196        mut params: lsp::PublishDiagnosticsParams,
6197        disk_based_sources: &[String],
6198        cx: &mut ModelContext<Self>,
6199    ) -> Result<()> {
6200        let abs_path = params
6201            .uri
6202            .to_file_path()
6203            .map_err(|_| anyhow!("URI is not a file"))?;
6204        let mut diagnostics = Vec::default();
6205        let mut primary_diagnostic_group_ids = HashMap::default();
6206        let mut sources_by_group_id = HashMap::default();
6207        let mut supporting_diagnostics = HashMap::default();
6208
6209        // Ensure that primary diagnostics are always the most severe
6210        params.diagnostics.sort_by_key(|item| item.severity);
6211
6212        for diagnostic in &params.diagnostics {
6213            let source = diagnostic.source.as_ref();
6214            let code = diagnostic.code.as_ref().map(|code| match code {
6215                lsp::NumberOrString::Number(code) => code.to_string(),
6216                lsp::NumberOrString::String(code) => code.clone(),
6217            });
6218            let range = range_from_lsp(diagnostic.range);
6219            let is_supporting = diagnostic
6220                .related_information
6221                .as_ref()
6222                .map_or(false, |infos| {
6223                    infos.iter().any(|info| {
6224                        primary_diagnostic_group_ids.contains_key(&(
6225                            source,
6226                            code.clone(),
6227                            range_from_lsp(info.location.range),
6228                        ))
6229                    })
6230                });
6231
6232            let is_unnecessary = diagnostic.tags.as_ref().map_or(false, |tags| {
6233                tags.iter().any(|tag| *tag == DiagnosticTag::UNNECESSARY)
6234            });
6235
6236            if is_supporting {
6237                supporting_diagnostics.insert(
6238                    (source, code.clone(), range),
6239                    (diagnostic.severity, is_unnecessary),
6240                );
6241            } else {
6242                let group_id = post_inc(&mut self.next_diagnostic_group_id);
6243                let is_disk_based =
6244                    source.map_or(false, |source| disk_based_sources.contains(source));
6245
6246                sources_by_group_id.insert(group_id, source);
6247                primary_diagnostic_group_ids
6248                    .insert((source, code.clone(), range.clone()), group_id);
6249
6250                diagnostics.push(DiagnosticEntry {
6251                    range,
6252                    diagnostic: Diagnostic {
6253                        source: diagnostic.source.clone(),
6254                        code: code.clone(),
6255                        severity: diagnostic.severity.unwrap_or(DiagnosticSeverity::ERROR),
6256                        message: diagnostic.message.trim().to_string(),
6257                        group_id,
6258                        is_primary: true,
6259                        is_disk_based,
6260                        is_unnecessary,
6261                        data: diagnostic.data.clone(),
6262                    },
6263                });
6264                if let Some(infos) = &diagnostic.related_information {
6265                    for info in infos {
6266                        if info.location.uri == params.uri && !info.message.is_empty() {
6267                            let range = range_from_lsp(info.location.range);
6268                            diagnostics.push(DiagnosticEntry {
6269                                range,
6270                                diagnostic: Diagnostic {
6271                                    source: diagnostic.source.clone(),
6272                                    code: code.clone(),
6273                                    severity: DiagnosticSeverity::INFORMATION,
6274                                    message: info.message.trim().to_string(),
6275                                    group_id,
6276                                    is_primary: false,
6277                                    is_disk_based,
6278                                    is_unnecessary: false,
6279                                    data: diagnostic.data.clone(),
6280                                },
6281                            });
6282                        }
6283                    }
6284                }
6285            }
6286        }
6287
6288        for entry in &mut diagnostics {
6289            let diagnostic = &mut entry.diagnostic;
6290            if !diagnostic.is_primary {
6291                let source = *sources_by_group_id.get(&diagnostic.group_id).unwrap();
6292                if let Some(&(severity, is_unnecessary)) = supporting_diagnostics.get(&(
6293                    source,
6294                    diagnostic.code.clone(),
6295                    entry.range.clone(),
6296                )) {
6297                    if let Some(severity) = severity {
6298                        diagnostic.severity = severity;
6299                    }
6300                    diagnostic.is_unnecessary = is_unnecessary;
6301                }
6302            }
6303        }
6304
6305        self.update_diagnostic_entries(
6306            language_server_id,
6307            abs_path,
6308            params.version,
6309            diagnostics,
6310            cx,
6311        )?;
6312        Ok(())
6313    }
6314
6315    fn insert_newly_running_language_server(
6316        &mut self,
6317        language: LanguageName,
6318        adapter: Arc<CachedLspAdapter>,
6319        language_server: Arc<LanguageServer>,
6320        server_id: LanguageServerId,
6321        key: (WorktreeId, LanguageServerName),
6322        cx: &mut ModelContext<Self>,
6323    ) {
6324        // If the language server for this key doesn't match the server id, don't store the
6325        // server. Which will cause it to be dropped, killing the process
6326        if self
6327            .language_server_ids
6328            .get(&key)
6329            .map(|id| id != &server_id)
6330            .unwrap_or(false)
6331        {
6332            return;
6333        }
6334
6335        // Update language_servers collection with Running variant of LanguageServerState
6336        // indicating that the server is up and running and ready
6337        if let Some(local) = self.as_local_mut() {
6338            local.language_servers.insert(
6339                server_id,
6340                LanguageServerState::Running {
6341                    adapter: adapter.clone(),
6342                    language: language.clone(),
6343                    server: language_server.clone(),
6344                    simulate_disk_based_diagnostics_completion: None,
6345                },
6346            );
6347        }
6348
6349        self.language_server_statuses.insert(
6350            server_id,
6351            LanguageServerStatus {
6352                name: language_server.name().to_string(),
6353                pending_work: Default::default(),
6354                has_pending_diagnostic_updates: false,
6355                progress_tokens: Default::default(),
6356            },
6357        );
6358
6359        cx.emit(LspStoreEvent::LanguageServerAdded(server_id));
6360
6361        if let Some((downstream_client, project_id)) = self.downstream_client.as_ref() {
6362            downstream_client
6363                .send(proto::StartLanguageServer {
6364                    project_id: *project_id,
6365                    server: Some(proto::LanguageServer {
6366                        id: server_id.0 as u64,
6367                        name: language_server.name().to_string(),
6368                    }),
6369                })
6370                .log_err();
6371        }
6372
6373        // Tell the language server about every open buffer in the worktree that matches the language.
6374        self.buffer_store.update(cx, |buffer_store, cx| {
6375            for buffer_handle in buffer_store.buffers() {
6376                let buffer = buffer_handle.read(cx);
6377                let file = match File::from_dyn(buffer.file()) {
6378                    Some(file) => file,
6379                    None => continue,
6380                };
6381                let language = match buffer.language() {
6382                    Some(language) => language,
6383                    None => continue,
6384                };
6385
6386                if file.worktree.read(cx).id() != key.0
6387                    || !self
6388                        .languages
6389                        .lsp_adapters(&language.name())
6390                        .iter()
6391                        .any(|a| a.name == key.1)
6392                {
6393                    continue;
6394                }
6395
6396                let file = match file.as_local() {
6397                    Some(file) => file,
6398                    None => continue,
6399                };
6400
6401                let versions = self
6402                    .buffer_snapshots
6403                    .entry(buffer.remote_id())
6404                    .or_default()
6405                    .entry(server_id)
6406                    .or_insert_with(|| {
6407                        vec![LspBufferSnapshot {
6408                            version: 0,
6409                            snapshot: buffer.text_snapshot(),
6410                        }]
6411                    });
6412
6413                let snapshot = versions.last().unwrap();
6414                let version = snapshot.version;
6415                let initial_snapshot = &snapshot.snapshot;
6416                let uri = lsp::Url::from_file_path(file.abs_path(cx)).unwrap();
6417                language_server
6418                    .notify::<lsp::notification::DidOpenTextDocument>(
6419                        lsp::DidOpenTextDocumentParams {
6420                            text_document: lsp::TextDocumentItem::new(
6421                                uri,
6422                                adapter.language_id(&language.name()),
6423                                version,
6424                                initial_snapshot.text(),
6425                            ),
6426                        },
6427                    )
6428                    .log_err();
6429
6430                buffer_handle.update(cx, |buffer, cx| {
6431                    buffer.set_completion_triggers(
6432                        language_server
6433                            .capabilities()
6434                            .completion_provider
6435                            .as_ref()
6436                            .and_then(|provider| provider.trigger_characters.clone())
6437                            .unwrap_or_default(),
6438                        cx,
6439                    )
6440                });
6441            }
6442        });
6443
6444        cx.notify();
6445    }
6446
6447    fn buffer_snapshot_for_lsp_version(
6448        &mut self,
6449        buffer: &Model<Buffer>,
6450        server_id: LanguageServerId,
6451        version: Option<i32>,
6452        cx: &AppContext,
6453    ) -> Result<TextBufferSnapshot> {
6454        const OLD_VERSIONS_TO_RETAIN: i32 = 10;
6455
6456        if let Some(version) = version {
6457            let buffer_id = buffer.read(cx).remote_id();
6458            let snapshots = self
6459                .buffer_snapshots
6460                .get_mut(&buffer_id)
6461                .and_then(|m| m.get_mut(&server_id))
6462                .ok_or_else(|| {
6463                    anyhow!("no snapshots found for buffer {buffer_id} and server {server_id}")
6464                })?;
6465
6466            let found_snapshot = snapshots
6467                .binary_search_by_key(&version, |e| e.version)
6468                .map(|ix| snapshots[ix].snapshot.clone())
6469                .map_err(|_| {
6470                    anyhow!("snapshot not found for buffer {buffer_id} server {server_id} at version {version}")
6471                })?;
6472
6473            snapshots.retain(|snapshot| snapshot.version + OLD_VERSIONS_TO_RETAIN >= version);
6474            Ok(found_snapshot)
6475        } else {
6476            Ok((buffer.read(cx)).text_snapshot())
6477        }
6478    }
6479
6480    pub fn language_servers_running_disk_based_diagnostics(
6481        &self,
6482    ) -> impl Iterator<Item = LanguageServerId> + '_ {
6483        self.language_server_statuses
6484            .iter()
6485            .filter_map(|(id, status)| {
6486                if status.has_pending_diagnostic_updates {
6487                    Some(*id)
6488                } else {
6489                    None
6490                }
6491            })
6492    }
6493
6494    pub(crate) fn language_servers_for_buffer<'a>(
6495        &'a self,
6496        buffer: &'a Buffer,
6497        cx: &'a AppContext,
6498    ) -> impl Iterator<Item = (&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
6499        self.language_server_ids_for_buffer(buffer, cx)
6500            .into_iter()
6501            .filter_map(
6502                |server_id| match self.as_local()?.language_servers.get(&server_id)? {
6503                    LanguageServerState::Running {
6504                        adapter, server, ..
6505                    } => Some((adapter, server)),
6506                    _ => None,
6507                },
6508            )
6509    }
6510
6511    pub(crate) fn cancel_language_server_work_for_buffers(
6512        &mut self,
6513        buffers: impl IntoIterator<Item = Model<Buffer>>,
6514        cx: &mut ModelContext<Self>,
6515    ) {
6516        let servers = buffers
6517            .into_iter()
6518            .flat_map(|buffer| {
6519                self.language_server_ids_for_buffer(buffer.read(cx), cx)
6520                    .into_iter()
6521            })
6522            .collect::<HashSet<_>>();
6523
6524        for server_id in servers {
6525            self.cancel_language_server_work(server_id, None, cx);
6526        }
6527    }
6528
6529    pub fn language_servers(
6530        &self,
6531    ) -> impl '_ + Iterator<Item = (LanguageServerId, LanguageServerName, WorktreeId)> {
6532        self.language_server_ids
6533            .iter()
6534            .map(|((worktree_id, server_name), server_id)| {
6535                (*server_id, server_name.clone(), *worktree_id)
6536            })
6537    }
6538
6539    fn register_supplementary_language_server(
6540        &mut self,
6541        id: LanguageServerId,
6542        name: LanguageServerName,
6543        server: Arc<LanguageServer>,
6544        cx: &mut ModelContext<Self>,
6545    ) {
6546        if let Some(local) = self.as_local_mut() {
6547            local
6548                .supplementary_language_servers
6549                .insert(id, (name, server));
6550            cx.emit(LspStoreEvent::LanguageServerAdded(id));
6551        }
6552    }
6553
6554    fn unregister_supplementary_language_server(
6555        &mut self,
6556        id: LanguageServerId,
6557        cx: &mut ModelContext<Self>,
6558    ) {
6559        if let Some(local) = self.as_local_mut() {
6560            local.supplementary_language_servers.remove(&id);
6561            cx.emit(LspStoreEvent::LanguageServerRemoved(id));
6562        }
6563    }
6564
6565    pub fn supplementary_language_servers(
6566        &self,
6567    ) -> impl '_ + Iterator<Item = (LanguageServerId, LanguageServerName)> {
6568        self.as_local().into_iter().flat_map(|local| {
6569            local
6570                .supplementary_language_servers
6571                .iter()
6572                .map(|(id, (name, _))| (*id, name.clone()))
6573        })
6574    }
6575
6576    pub fn language_server_adapter_for_id(
6577        &self,
6578        id: LanguageServerId,
6579    ) -> Option<Arc<CachedLspAdapter>> {
6580        self.as_local()
6581            .and_then(|local| local.language_servers.get(&id))
6582            .and_then(|language_server_state| match language_server_state {
6583                LanguageServerState::Running { adapter, .. } => Some(adapter.clone()),
6584                _ => None,
6585            })
6586    }
6587
6588    pub(super) fn update_local_worktree_language_servers(
6589        &mut self,
6590        worktree_handle: &Model<Worktree>,
6591        changes: &[(Arc<Path>, ProjectEntryId, PathChange)],
6592        cx: &mut ModelContext<Self>,
6593    ) {
6594        if changes.is_empty() {
6595            return;
6596        }
6597
6598        let Some(local) = self.as_local() else { return };
6599
6600        local.prettier_store.update(cx, |prettier_store, cx| {
6601            prettier_store.update_prettier_settings(&worktree_handle, changes, cx)
6602        });
6603
6604        let worktree_id = worktree_handle.read(cx).id();
6605        let mut language_server_ids = self
6606            .language_server_ids
6607            .iter()
6608            .filter_map(|((server_worktree_id, _), server_id)| {
6609                (*server_worktree_id == worktree_id).then_some(*server_id)
6610            })
6611            .collect::<Vec<_>>();
6612        language_server_ids.sort();
6613        language_server_ids.dedup();
6614
6615        let abs_path = worktree_handle.read(cx).abs_path();
6616        for server_id in &language_server_ids {
6617            if let Some(LanguageServerState::Running { server, .. }) =
6618                local.language_servers.get(server_id)
6619            {
6620                if let Some(watched_paths) = local
6621                    .language_server_watched_paths
6622                    .get(server_id)
6623                    .and_then(|paths| paths.read(cx).worktree_paths.get(&worktree_id))
6624                {
6625                    let params = lsp::DidChangeWatchedFilesParams {
6626                        changes: changes
6627                            .iter()
6628                            .filter_map(|(path, _, change)| {
6629                                if !watched_paths.is_match(path) {
6630                                    return None;
6631                                }
6632                                let typ = match change {
6633                                    PathChange::Loaded => return None,
6634                                    PathChange::Added => lsp::FileChangeType::CREATED,
6635                                    PathChange::Removed => lsp::FileChangeType::DELETED,
6636                                    PathChange::Updated => lsp::FileChangeType::CHANGED,
6637                                    PathChange::AddedOrUpdated => lsp::FileChangeType::CHANGED,
6638                                };
6639                                Some(lsp::FileEvent {
6640                                    uri: lsp::Url::from_file_path(abs_path.join(path)).unwrap(),
6641                                    typ,
6642                                })
6643                            })
6644                            .collect(),
6645                    };
6646                    if !params.changes.is_empty() {
6647                        server
6648                            .notify::<lsp::notification::DidChangeWatchedFiles>(params)
6649                            .log_err();
6650                    }
6651                }
6652            }
6653        }
6654    }
6655
6656    pub(crate) fn cancel_language_server_work(
6657        &mut self,
6658        server_id: LanguageServerId,
6659        token_to_cancel: Option<String>,
6660        _cx: &mut ModelContext<Self>,
6661    ) {
6662        let Some(local) = self.as_local() else {
6663            return;
6664        };
6665        let status = self.language_server_statuses.get(&server_id);
6666        let server = local.language_servers.get(&server_id);
6667        if let Some((LanguageServerState::Running { server, .. }, status)) = server.zip(status) {
6668            for (token, progress) in &status.pending_work {
6669                if let Some(token_to_cancel) = token_to_cancel.as_ref() {
6670                    if token != token_to_cancel {
6671                        continue;
6672                    }
6673                }
6674                if progress.is_cancellable {
6675                    server
6676                        .notify::<lsp::notification::WorkDoneProgressCancel>(
6677                            WorkDoneProgressCancelParams {
6678                                token: lsp::NumberOrString::String(token.clone()),
6679                            },
6680                        )
6681                        .ok();
6682                }
6683
6684                if progress.is_cancellable {
6685                    server
6686                        .notify::<lsp::notification::WorkDoneProgressCancel>(
6687                            WorkDoneProgressCancelParams {
6688                                token: lsp::NumberOrString::String(token.clone()),
6689                            },
6690                        )
6691                        .ok();
6692                }
6693            }
6694        }
6695    }
6696
6697    pub fn wait_for_remote_buffer(
6698        &mut self,
6699        id: BufferId,
6700        cx: &mut ModelContext<Self>,
6701    ) -> Task<Result<Model<Buffer>>> {
6702        self.buffer_store.update(cx, |buffer_store, cx| {
6703            buffer_store.wait_for_remote_buffer(id, cx)
6704        })
6705    }
6706
6707    pub(crate) fn language_server_ids_for_buffer(
6708        &self,
6709        buffer: &Buffer,
6710        cx: &AppContext,
6711    ) -> Vec<LanguageServerId> {
6712        if let Some((file, language)) = File::from_dyn(buffer.file()).zip(buffer.language()) {
6713            let worktree_id = file.worktree_id(cx);
6714            self.languages
6715                .lsp_adapters(&language.name())
6716                .iter()
6717                .flat_map(|adapter| {
6718                    let key = (worktree_id, adapter.name.clone());
6719                    self.language_server_ids.get(&key).copied()
6720                })
6721                .collect()
6722        } else {
6723            Vec::new()
6724        }
6725    }
6726
6727    pub async fn deserialize_text_edits(
6728        this: Model<Self>,
6729        buffer_to_edit: Model<Buffer>,
6730        edits: Vec<lsp::TextEdit>,
6731        push_to_history: bool,
6732        _: Arc<CachedLspAdapter>,
6733        language_server: Arc<LanguageServer>,
6734        cx: &mut AsyncAppContext,
6735    ) -> Result<Option<Transaction>> {
6736        let edits = this
6737            .update(cx, |this, cx| {
6738                this.edits_from_lsp(
6739                    &buffer_to_edit,
6740                    edits,
6741                    language_server.server_id(),
6742                    None,
6743                    cx,
6744                )
6745            })?
6746            .await?;
6747
6748        let transaction = buffer_to_edit.update(cx, |buffer, cx| {
6749            buffer.finalize_last_transaction();
6750            buffer.start_transaction();
6751            for (range, text) in edits {
6752                buffer.edit([(range, text)], None, cx);
6753            }
6754
6755            if buffer.end_transaction(cx).is_some() {
6756                let transaction = buffer.finalize_last_transaction().unwrap().clone();
6757                if !push_to_history {
6758                    buffer.forget_transaction(transaction.id);
6759                }
6760                Some(transaction)
6761            } else {
6762                None
6763            }
6764        })?;
6765
6766        Ok(transaction)
6767    }
6768
6769    pub async fn deserialize_workspace_edit(
6770        this: Model<Self>,
6771        edit: lsp::WorkspaceEdit,
6772        push_to_history: bool,
6773        lsp_adapter: Arc<CachedLspAdapter>,
6774        language_server: Arc<LanguageServer>,
6775        cx: &mut AsyncAppContext,
6776    ) -> Result<ProjectTransaction> {
6777        let fs = this.read_with(cx, |this, _| this.as_local().unwrap().fs.clone())?;
6778
6779        let mut operations = Vec::new();
6780        if let Some(document_changes) = edit.document_changes {
6781            match document_changes {
6782                lsp::DocumentChanges::Edits(edits) => {
6783                    operations.extend(edits.into_iter().map(lsp::DocumentChangeOperation::Edit))
6784                }
6785                lsp::DocumentChanges::Operations(ops) => operations = ops,
6786            }
6787        } else if let Some(changes) = edit.changes {
6788            operations.extend(changes.into_iter().map(|(uri, edits)| {
6789                lsp::DocumentChangeOperation::Edit(lsp::TextDocumentEdit {
6790                    text_document: lsp::OptionalVersionedTextDocumentIdentifier {
6791                        uri,
6792                        version: None,
6793                    },
6794                    edits: edits.into_iter().map(Edit::Plain).collect(),
6795                })
6796            }));
6797        }
6798
6799        let mut project_transaction = ProjectTransaction::default();
6800        for operation in operations {
6801            match operation {
6802                lsp::DocumentChangeOperation::Op(lsp::ResourceOp::Create(op)) => {
6803                    let abs_path = op
6804                        .uri
6805                        .to_file_path()
6806                        .map_err(|_| anyhow!("can't convert URI to path"))?;
6807
6808                    if let Some(parent_path) = abs_path.parent() {
6809                        fs.create_dir(parent_path).await?;
6810                    }
6811                    if abs_path.ends_with("/") {
6812                        fs.create_dir(&abs_path).await?;
6813                    } else {
6814                        fs.create_file(
6815                            &abs_path,
6816                            op.options
6817                                .map(|options| fs::CreateOptions {
6818                                    overwrite: options.overwrite.unwrap_or(false),
6819                                    ignore_if_exists: options.ignore_if_exists.unwrap_or(false),
6820                                })
6821                                .unwrap_or_default(),
6822                        )
6823                        .await?;
6824                    }
6825                }
6826
6827                lsp::DocumentChangeOperation::Op(lsp::ResourceOp::Rename(op)) => {
6828                    let source_abs_path = op
6829                        .old_uri
6830                        .to_file_path()
6831                        .map_err(|_| anyhow!("can't convert URI to path"))?;
6832                    let target_abs_path = op
6833                        .new_uri
6834                        .to_file_path()
6835                        .map_err(|_| anyhow!("can't convert URI to path"))?;
6836                    fs.rename(
6837                        &source_abs_path,
6838                        &target_abs_path,
6839                        op.options
6840                            .map(|options| fs::RenameOptions {
6841                                overwrite: options.overwrite.unwrap_or(false),
6842                                ignore_if_exists: options.ignore_if_exists.unwrap_or(false),
6843                            })
6844                            .unwrap_or_default(),
6845                    )
6846                    .await?;
6847                }
6848
6849                lsp::DocumentChangeOperation::Op(lsp::ResourceOp::Delete(op)) => {
6850                    let abs_path = op
6851                        .uri
6852                        .to_file_path()
6853                        .map_err(|_| anyhow!("can't convert URI to path"))?;
6854                    let options = op
6855                        .options
6856                        .map(|options| fs::RemoveOptions {
6857                            recursive: options.recursive.unwrap_or(false),
6858                            ignore_if_not_exists: options.ignore_if_not_exists.unwrap_or(false),
6859                        })
6860                        .unwrap_or_default();
6861                    if abs_path.ends_with("/") {
6862                        fs.remove_dir(&abs_path, options).await?;
6863                    } else {
6864                        fs.remove_file(&abs_path, options).await?;
6865                    }
6866                }
6867
6868                lsp::DocumentChangeOperation::Edit(op) => {
6869                    let buffer_to_edit = this
6870                        .update(cx, |this, cx| {
6871                            this.open_local_buffer_via_lsp(
6872                                op.text_document.uri.clone(),
6873                                language_server.server_id(),
6874                                lsp_adapter.name.clone(),
6875                                cx,
6876                            )
6877                        })?
6878                        .await?;
6879
6880                    let edits = this
6881                        .update(cx, |this, cx| {
6882                            let path = buffer_to_edit.read(cx).project_path(cx);
6883                            let active_entry = this.active_entry;
6884                            let is_active_entry = path.clone().map_or(false, |project_path| {
6885                                this.worktree_store
6886                                    .read(cx)
6887                                    .entry_for_path(&project_path, cx)
6888                                    .map_or(false, |entry| Some(entry.id) == active_entry)
6889                            });
6890
6891                            let (mut edits, mut snippet_edits) = (vec![], vec![]);
6892                            for edit in op.edits {
6893                                match edit {
6894                                    Edit::Plain(edit) => edits.push(edit),
6895                                    Edit::Annotated(edit) => edits.push(edit.text_edit),
6896                                    Edit::Snippet(edit) => {
6897                                        let Ok(snippet) = Snippet::parse(&edit.snippet.value)
6898                                        else {
6899                                            continue;
6900                                        };
6901
6902                                        if is_active_entry {
6903                                            snippet_edits.push((edit.range, snippet));
6904                                        } else {
6905                                            // Since this buffer is not focused, apply a normal edit.
6906                                            edits.push(TextEdit {
6907                                                range: edit.range,
6908                                                new_text: snippet.text,
6909                                            });
6910                                        }
6911                                    }
6912                                }
6913                            }
6914                            if !snippet_edits.is_empty() {
6915                                let buffer_id = buffer_to_edit.read(cx).remote_id();
6916                                let version = if let Some(buffer_version) = op.text_document.version
6917                                {
6918                                    this.buffer_snapshot_for_lsp_version(
6919                                        &buffer_to_edit,
6920                                        language_server.server_id(),
6921                                        Some(buffer_version),
6922                                        cx,
6923                                    )
6924                                    .ok()
6925                                    .map(|snapshot| snapshot.version)
6926                                } else {
6927                                    Some(buffer_to_edit.read(cx).saved_version().clone())
6928                                };
6929
6930                                let most_recent_edit = version.and_then(|version| {
6931                                    version.iter().max_by_key(|timestamp| timestamp.value)
6932                                });
6933                                // Check if the edit that triggered that edit has been made by this participant.
6934
6935                                if let Some(most_recent_edit) = most_recent_edit {
6936                                    cx.emit(LspStoreEvent::SnippetEdit {
6937                                        buffer_id,
6938                                        edits: snippet_edits,
6939                                        most_recent_edit,
6940                                    });
6941                                }
6942                            }
6943
6944                            this.edits_from_lsp(
6945                                &buffer_to_edit,
6946                                edits,
6947                                language_server.server_id(),
6948                                op.text_document.version,
6949                                cx,
6950                            )
6951                        })?
6952                        .await?;
6953
6954                    let transaction = buffer_to_edit.update(cx, |buffer, cx| {
6955                        buffer.finalize_last_transaction();
6956                        buffer.start_transaction();
6957                        for (range, text) in edits {
6958                            buffer.edit([(range, text)], None, cx);
6959                        }
6960                        let transaction = if buffer.end_transaction(cx).is_some() {
6961                            let transaction = buffer.finalize_last_transaction().unwrap().clone();
6962                            if !push_to_history {
6963                                buffer.forget_transaction(transaction.id);
6964                            }
6965                            Some(transaction)
6966                        } else {
6967                            None
6968                        };
6969
6970                        transaction
6971                    })?;
6972                    if let Some(transaction) = transaction {
6973                        project_transaction.0.insert(buffer_to_edit, transaction);
6974                    }
6975                }
6976            }
6977        }
6978
6979        Ok(project_transaction)
6980    }
6981
6982    fn serialize_symbol(symbol: &Symbol) -> proto::Symbol {
6983        proto::Symbol {
6984            language_server_name: symbol.language_server_name.0.to_string(),
6985            source_worktree_id: symbol.source_worktree_id.to_proto(),
6986            worktree_id: symbol.path.worktree_id.to_proto(),
6987            path: symbol.path.path.to_string_lossy().to_string(),
6988            name: symbol.name.clone(),
6989            kind: unsafe { mem::transmute::<lsp::SymbolKind, i32>(symbol.kind) },
6990            start: Some(proto::PointUtf16 {
6991                row: symbol.range.start.0.row,
6992                column: symbol.range.start.0.column,
6993            }),
6994            end: Some(proto::PointUtf16 {
6995                row: symbol.range.end.0.row,
6996                column: symbol.range.end.0.column,
6997            }),
6998            signature: symbol.signature.to_vec(),
6999        }
7000    }
7001
7002    fn deserialize_symbol(serialized_symbol: proto::Symbol) -> Result<CoreSymbol> {
7003        let source_worktree_id = WorktreeId::from_proto(serialized_symbol.source_worktree_id);
7004        let worktree_id = WorktreeId::from_proto(serialized_symbol.worktree_id);
7005        let kind = unsafe { mem::transmute::<i32, lsp::SymbolKind>(serialized_symbol.kind) };
7006        let path = ProjectPath {
7007            worktree_id,
7008            path: PathBuf::from(serialized_symbol.path).into(),
7009        };
7010
7011        let start = serialized_symbol
7012            .start
7013            .ok_or_else(|| anyhow!("invalid start"))?;
7014        let end = serialized_symbol
7015            .end
7016            .ok_or_else(|| anyhow!("invalid end"))?;
7017        Ok(CoreSymbol {
7018            language_server_name: LanguageServerName(serialized_symbol.language_server_name.into()),
7019            source_worktree_id,
7020            path,
7021            name: serialized_symbol.name,
7022            range: Unclipped(PointUtf16::new(start.row, start.column))
7023                ..Unclipped(PointUtf16::new(end.row, end.column)),
7024            kind,
7025            signature: serialized_symbol
7026                .signature
7027                .try_into()
7028                .map_err(|_| anyhow!("invalid signature"))?,
7029        })
7030    }
7031
7032    pub(crate) fn serialize_completion(completion: &CoreCompletion) -> proto::Completion {
7033        proto::Completion {
7034            old_start: Some(serialize_anchor(&completion.old_range.start)),
7035            old_end: Some(serialize_anchor(&completion.old_range.end)),
7036            new_text: completion.new_text.clone(),
7037            server_id: completion.server_id.0 as u64,
7038            lsp_completion: serde_json::to_vec(&completion.lsp_completion).unwrap(),
7039        }
7040    }
7041
7042    pub(crate) fn deserialize_completion(completion: proto::Completion) -> Result<CoreCompletion> {
7043        let old_start = completion
7044            .old_start
7045            .and_then(deserialize_anchor)
7046            .ok_or_else(|| anyhow!("invalid old start"))?;
7047        let old_end = completion
7048            .old_end
7049            .and_then(deserialize_anchor)
7050            .ok_or_else(|| anyhow!("invalid old end"))?;
7051        let lsp_completion = serde_json::from_slice(&completion.lsp_completion)?;
7052
7053        Ok(CoreCompletion {
7054            old_range: old_start..old_end,
7055            new_text: completion.new_text,
7056            server_id: LanguageServerId(completion.server_id as usize),
7057            lsp_completion,
7058        })
7059    }
7060
7061    pub(crate) fn serialize_code_action(action: &CodeAction) -> proto::CodeAction {
7062        proto::CodeAction {
7063            server_id: action.server_id.0 as u64,
7064            start: Some(serialize_anchor(&action.range.start)),
7065            end: Some(serialize_anchor(&action.range.end)),
7066            lsp_action: serde_json::to_vec(&action.lsp_action).unwrap(),
7067        }
7068    }
7069
7070    pub(crate) fn deserialize_code_action(action: proto::CodeAction) -> Result<CodeAction> {
7071        let start = action
7072            .start
7073            .and_then(deserialize_anchor)
7074            .ok_or_else(|| anyhow!("invalid start"))?;
7075        let end = action
7076            .end
7077            .and_then(deserialize_anchor)
7078            .ok_or_else(|| anyhow!("invalid end"))?;
7079        let lsp_action = serde_json::from_slice(&action.lsp_action)?;
7080        Ok(CodeAction {
7081            server_id: LanguageServerId(action.server_id as usize),
7082            range: start..end,
7083            lsp_action,
7084        })
7085    }
7086}
7087
7088impl EventEmitter<LspStoreEvent> for LspStore {}
7089
7090fn remove_empty_hover_blocks(mut hover: Hover) -> Option<Hover> {
7091    hover
7092        .contents
7093        .retain(|hover_block| !hover_block.text.trim().is_empty());
7094    if hover.contents.is_empty() {
7095        None
7096    } else {
7097        Some(hover)
7098    }
7099}
7100
7101async fn populate_labels_for_completions(
7102    mut new_completions: Vec<CoreCompletion>,
7103    language_registry: &Arc<LanguageRegistry>,
7104    language: Option<Arc<Language>>,
7105    lsp_adapter: Option<Arc<CachedLspAdapter>>,
7106    completions: &mut Vec<Completion>,
7107) {
7108    let lsp_completions = new_completions
7109        .iter_mut()
7110        .map(|completion| mem::take(&mut completion.lsp_completion))
7111        .collect::<Vec<_>>();
7112
7113    let labels = if let Some((language, lsp_adapter)) = language.as_ref().zip(lsp_adapter) {
7114        lsp_adapter
7115            .labels_for_completions(&lsp_completions, language)
7116            .await
7117            .log_err()
7118            .unwrap_or_default()
7119    } else {
7120        Vec::new()
7121    };
7122
7123    for ((completion, lsp_completion), label) in new_completions
7124        .into_iter()
7125        .zip(lsp_completions)
7126        .zip(labels.into_iter().chain(iter::repeat(None)))
7127    {
7128        let documentation = if let Some(docs) = &lsp_completion.documentation {
7129            Some(prepare_completion_documentation(docs, language_registry, language.clone()).await)
7130        } else {
7131            None
7132        };
7133
7134        completions.push(Completion {
7135            old_range: completion.old_range,
7136            new_text: completion.new_text,
7137            label: label.unwrap_or_else(|| {
7138                CodeLabel::plain(
7139                    lsp_completion.label.clone(),
7140                    lsp_completion.filter_text.as_deref(),
7141                )
7142            }),
7143            server_id: completion.server_id,
7144            documentation,
7145            lsp_completion,
7146            confirm: None,
7147        })
7148    }
7149}
7150
7151#[derive(Debug)]
7152pub enum LanguageServerToQuery {
7153    Primary,
7154    Other(LanguageServerId),
7155}
7156
7157#[derive(Default)]
7158struct LanguageServerWatchedPaths {
7159    worktree_paths: HashMap<WorktreeId, GlobSet>,
7160    abs_paths: HashMap<Arc<Path>, (GlobSet, Task<()>)>,
7161}
7162
7163#[derive(Default)]
7164struct LanguageServerWatchedPathsBuilder {
7165    worktree_paths: HashMap<WorktreeId, GlobSet>,
7166    abs_paths: HashMap<Arc<Path>, GlobSet>,
7167}
7168
7169impl LanguageServerWatchedPathsBuilder {
7170    fn watch_worktree(&mut self, worktree_id: WorktreeId, glob_set: GlobSet) {
7171        self.worktree_paths.insert(worktree_id, glob_set);
7172    }
7173    fn watch_abs_path(&mut self, path: Arc<Path>, glob_set: GlobSet) {
7174        self.abs_paths.insert(path, glob_set);
7175    }
7176    fn build(
7177        self,
7178        fs: Arc<dyn Fs>,
7179        language_server_id: LanguageServerId,
7180        cx: &mut ModelContext<LspStore>,
7181    ) -> Model<LanguageServerWatchedPaths> {
7182        let project = cx.weak_model();
7183
7184        cx.new_model(|cx| {
7185            let this_id = cx.entity_id();
7186            const LSP_ABS_PATH_OBSERVE: Duration = Duration::from_millis(100);
7187            let abs_paths = self
7188                .abs_paths
7189                .into_iter()
7190                .map(|(abs_path, globset)| {
7191                    let task = cx.spawn({
7192                        let abs_path = abs_path.clone();
7193                        let fs = fs.clone();
7194
7195                        let lsp_store = project.clone();
7196                        |_, mut cx| async move {
7197                            maybe!(async move {
7198                                let mut push_updates =
7199                                    fs.watch(&abs_path, LSP_ABS_PATH_OBSERVE).await;
7200                                while let Some(update) = push_updates.0.next().await {
7201                                    let action = lsp_store
7202                                        .update(&mut cx, |this, cx| {
7203                                            let Some(local) = this.as_local() else {
7204                                                return ControlFlow::Break(());
7205                                            };
7206                                            let Some(watcher) = local
7207                                                .language_server_watched_paths
7208                                                .get(&language_server_id)
7209                                            else {
7210                                                return ControlFlow::Break(());
7211                                            };
7212                                            if watcher.entity_id() != this_id {
7213                                                // This watcher is no longer registered on the project, which means that we should
7214                                                // cease operations.
7215                                                return ControlFlow::Break(());
7216                                            }
7217                                            let (globs, _) = watcher
7218                                                .read(cx)
7219                                                .abs_paths
7220                                                .get(&abs_path)
7221                                                .expect(
7222                                                "Watched abs path is not registered with a watcher",
7223                                            );
7224                                            let matching_entries = update
7225                                                .into_iter()
7226                                                .filter(|event| globs.is_match(&event.path))
7227                                                .collect::<Vec<_>>();
7228                                            this.lsp_notify_abs_paths_changed(
7229                                                language_server_id,
7230                                                matching_entries,
7231                                            );
7232                                            ControlFlow::Continue(())
7233                                        })
7234                                        .ok()?;
7235
7236                                    if action.is_break() {
7237                                        break;
7238                                    }
7239                                }
7240                                Some(())
7241                            })
7242                            .await;
7243                        }
7244                    });
7245                    (abs_path, (globset, task))
7246                })
7247                .collect();
7248            LanguageServerWatchedPaths {
7249                worktree_paths: self.worktree_paths,
7250                abs_paths,
7251            }
7252        })
7253    }
7254}
7255
7256struct LspBufferSnapshot {
7257    version: i32,
7258    snapshot: TextBufferSnapshot,
7259}
7260
7261/// A prompt requested by LSP server.
7262#[derive(Clone, Debug)]
7263pub struct LanguageServerPromptRequest {
7264    pub level: PromptLevel,
7265    pub message: String,
7266    pub actions: Vec<MessageActionItem>,
7267    pub lsp_name: String,
7268    pub(crate) response_channel: Sender<MessageActionItem>,
7269}
7270
7271impl LanguageServerPromptRequest {
7272    pub async fn respond(self, index: usize) -> Option<()> {
7273        if let Some(response) = self.actions.into_iter().nth(index) {
7274            self.response_channel.send(response).await.ok()
7275        } else {
7276            None
7277        }
7278    }
7279}
7280impl PartialEq for LanguageServerPromptRequest {
7281    fn eq(&self, other: &Self) -> bool {
7282        self.message == other.message && self.actions == other.actions
7283    }
7284}
7285
7286#[derive(Clone, Debug, PartialEq)]
7287pub enum LanguageServerLogType {
7288    Log(MessageType),
7289    Trace(Option<String>),
7290}
7291
7292pub enum LanguageServerState {
7293    Starting(Task<Option<Arc<LanguageServer>>>),
7294
7295    Running {
7296        language: LanguageName,
7297        adapter: Arc<CachedLspAdapter>,
7298        server: Arc<LanguageServer>,
7299        simulate_disk_based_diagnostics_completion: Option<Task<()>>,
7300    },
7301}
7302
7303impl std::fmt::Debug for LanguageServerState {
7304    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7305        match self {
7306            LanguageServerState::Starting(_) => {
7307                f.debug_struct("LanguageServerState::Starting").finish()
7308            }
7309            LanguageServerState::Running { language, .. } => f
7310                .debug_struct("LanguageServerState::Running")
7311                .field("language", &language)
7312                .finish(),
7313        }
7314    }
7315}
7316
7317#[derive(Clone, Debug, Serialize)]
7318pub struct LanguageServerProgress {
7319    pub is_disk_based_diagnostics_progress: bool,
7320    pub is_cancellable: bool,
7321    pub title: Option<String>,
7322    pub message: Option<String>,
7323    pub percentage: Option<usize>,
7324    #[serde(skip_serializing)]
7325    pub last_update_at: Instant,
7326}
7327
7328#[derive(Copy, Clone, Debug, Default, PartialEq, Serialize)]
7329pub struct DiagnosticSummary {
7330    pub error_count: usize,
7331    pub warning_count: usize,
7332}
7333
7334impl DiagnosticSummary {
7335    pub fn new<'a, T: 'a>(diagnostics: impl IntoIterator<Item = &'a DiagnosticEntry<T>>) -> Self {
7336        let mut this = Self {
7337            error_count: 0,
7338            warning_count: 0,
7339        };
7340
7341        for entry in diagnostics {
7342            if entry.diagnostic.is_primary {
7343                match entry.diagnostic.severity {
7344                    DiagnosticSeverity::ERROR => this.error_count += 1,
7345                    DiagnosticSeverity::WARNING => this.warning_count += 1,
7346                    _ => {}
7347                }
7348            }
7349        }
7350
7351        this
7352    }
7353
7354    pub fn is_empty(&self) -> bool {
7355        self.error_count == 0 && self.warning_count == 0
7356    }
7357
7358    pub fn to_proto(
7359        &self,
7360        language_server_id: LanguageServerId,
7361        path: &Path,
7362    ) -> proto::DiagnosticSummary {
7363        proto::DiagnosticSummary {
7364            path: path.to_string_lossy().to_string(),
7365            language_server_id: language_server_id.0 as u64,
7366            error_count: self.error_count as u32,
7367            warning_count: self.warning_count as u32,
7368        }
7369    }
7370}
7371
7372fn glob_literal_prefix(glob: &str) -> &str {
7373    let is_absolute = glob.starts_with(path::MAIN_SEPARATOR);
7374
7375    let mut literal_end = is_absolute as usize;
7376    for (i, part) in glob.split(path::MAIN_SEPARATOR).enumerate() {
7377        if part.contains(['*', '?', '{', '}']) {
7378            break;
7379        } else {
7380            if i > 0 {
7381                // Account for separator prior to this part
7382                literal_end += path::MAIN_SEPARATOR.len_utf8();
7383            }
7384            literal_end += part.len();
7385        }
7386    }
7387    let literal_end = literal_end.min(glob.len());
7388    &glob[..literal_end]
7389}
7390
7391pub struct SshLspAdapter {
7392    name: LanguageServerName,
7393    binary: LanguageServerBinary,
7394    initialization_options: Option<String>,
7395    code_action_kinds: Option<Vec<CodeActionKind>>,
7396}
7397
7398impl SshLspAdapter {
7399    pub fn new(
7400        name: LanguageServerName,
7401        binary: LanguageServerBinary,
7402        initialization_options: Option<String>,
7403        code_action_kinds: Option<String>,
7404    ) -> Self {
7405        Self {
7406            name,
7407            binary,
7408            initialization_options,
7409            code_action_kinds: code_action_kinds
7410                .as_ref()
7411                .and_then(|c| serde_json::from_str(c).ok()),
7412        }
7413    }
7414}
7415
7416#[async_trait(?Send)]
7417impl LspAdapter for SshLspAdapter {
7418    fn name(&self) -> LanguageServerName {
7419        self.name.clone()
7420    }
7421
7422    async fn initialization_options(
7423        self: Arc<Self>,
7424        _: &Arc<dyn LspAdapterDelegate>,
7425    ) -> Result<Option<serde_json::Value>> {
7426        let Some(options) = &self.initialization_options else {
7427            return Ok(None);
7428        };
7429        let result = serde_json::from_str(options)?;
7430        Ok(result)
7431    }
7432
7433    fn code_action_kinds(&self) -> Option<Vec<CodeActionKind>> {
7434        self.code_action_kinds.clone()
7435    }
7436
7437    async fn check_if_user_installed(
7438        &self,
7439        _: &dyn LspAdapterDelegate,
7440        _: &AsyncAppContext,
7441    ) -> Option<LanguageServerBinary> {
7442        Some(self.binary.clone())
7443    }
7444
7445    async fn cached_server_binary(
7446        &self,
7447        _: PathBuf,
7448        _: &dyn LspAdapterDelegate,
7449    ) -> Option<LanguageServerBinary> {
7450        None
7451    }
7452
7453    async fn fetch_latest_server_version(
7454        &self,
7455        _: &dyn LspAdapterDelegate,
7456    ) -> Result<Box<dyn 'static + Send + Any>> {
7457        anyhow::bail!("SshLspAdapter does not support fetch_latest_server_version")
7458    }
7459
7460    async fn fetch_server_binary(
7461        &self,
7462        _: Box<dyn 'static + Send + Any>,
7463        _: PathBuf,
7464        _: &dyn LspAdapterDelegate,
7465    ) -> Result<LanguageServerBinary> {
7466        anyhow::bail!("SshLspAdapter does not support fetch_server_binary")
7467    }
7468}
7469
7470pub fn language_server_settings<'a, 'b: 'a>(
7471    delegate: &'a dyn LspAdapterDelegate,
7472    language: &LanguageServerName,
7473    cx: &'b AppContext,
7474) -> Option<&'a LspSettings> {
7475    ProjectSettings::get(
7476        Some(SettingsLocation {
7477            worktree_id: delegate.worktree_id(),
7478            path: delegate.worktree_root_path(),
7479        }),
7480        cx,
7481    )
7482    .lsp
7483    .get(language)
7484}
7485
7486pub struct LocalLspAdapterDelegate {
7487    lsp_store: WeakModel<LspStore>,
7488    worktree: worktree::Snapshot,
7489    fs: Arc<dyn Fs>,
7490    http_client: Arc<dyn HttpClient>,
7491    language_registry: Arc<LanguageRegistry>,
7492    load_shell_env_task: Shared<Task<Option<HashMap<String, String>>>>,
7493}
7494
7495impl LocalLspAdapterDelegate {
7496    fn for_local(
7497        lsp_store: &LspStore,
7498        worktree: &Model<Worktree>,
7499        cx: &mut ModelContext<LspStore>,
7500    ) -> Arc<Self> {
7501        let local = lsp_store
7502            .as_local()
7503            .expect("LocalLspAdapterDelegate cannot be constructed on a remote");
7504
7505        let http_client = local
7506            .http_client
7507            .clone()
7508            .unwrap_or_else(|| Arc::new(BlockedHttpClient));
7509
7510        Self::new(lsp_store, worktree, http_client, local.fs.clone(), cx)
7511    }
7512
7513    pub fn new(
7514        lsp_store: &LspStore,
7515        worktree: &Model<Worktree>,
7516        http_client: Arc<dyn HttpClient>,
7517        fs: Arc<dyn Fs>,
7518        cx: &mut ModelContext<LspStore>,
7519    ) -> Arc<Self> {
7520        let worktree_id = worktree.read(cx).id();
7521        let worktree_abs_path = worktree.read(cx).abs_path();
7522        let load_shell_env_task = if let Some(environment) =
7523            &lsp_store.as_local().map(|local| local.environment.clone())
7524        {
7525            environment.update(cx, |env, cx| {
7526                env.get_environment(Some(worktree_id), Some(worktree_abs_path), cx)
7527            })
7528        } else {
7529            Task::ready(None).shared()
7530        };
7531
7532        Arc::new(Self {
7533            lsp_store: cx.weak_model(),
7534            worktree: worktree.read(cx).snapshot(),
7535            fs,
7536            http_client,
7537            language_registry: lsp_store.languages.clone(),
7538            load_shell_env_task,
7539        })
7540    }
7541}
7542
7543#[async_trait]
7544impl LspAdapterDelegate for LocalLspAdapterDelegate {
7545    fn show_notification(&self, message: &str, cx: &mut AppContext) {
7546        self.lsp_store
7547            .update(cx, |_, cx| {
7548                cx.emit(LspStoreEvent::Notification(message.to_owned()))
7549            })
7550            .ok();
7551    }
7552
7553    fn http_client(&self) -> Arc<dyn HttpClient> {
7554        self.http_client.clone()
7555    }
7556
7557    fn worktree_id(&self) -> WorktreeId {
7558        self.worktree.id()
7559    }
7560
7561    fn worktree_root_path(&self) -> &Path {
7562        self.worktree.abs_path().as_ref()
7563    }
7564
7565    async fn shell_env(&self) -> HashMap<String, String> {
7566        let task = self.load_shell_env_task.clone();
7567        task.await.unwrap_or_default()
7568    }
7569
7570    async fn npm_package_installed_version(
7571        &self,
7572        package_name: &str,
7573    ) -> Result<Option<(PathBuf, String)>> {
7574        let local_package_directory = self.worktree_root_path();
7575        let node_modules_directory = local_package_directory.join("node_modules");
7576
7577        if let Some(version) =
7578            read_package_installed_version(node_modules_directory.clone(), package_name).await?
7579        {
7580            return Ok(Some((node_modules_directory, version)));
7581        }
7582        let Some(npm) = self.which("npm".as_ref()).await else {
7583            log::warn!(
7584                "Failed to find npm executable for {:?}",
7585                local_package_directory
7586            );
7587            return Ok(None);
7588        };
7589
7590        let env = self.shell_env().await;
7591        let output = smol::process::Command::new(&npm)
7592            .args(["root", "-g"])
7593            .envs(env)
7594            .current_dir(local_package_directory)
7595            .output()
7596            .await?;
7597        let global_node_modules =
7598            PathBuf::from(String::from_utf8_lossy(&output.stdout).to_string());
7599
7600        if let Some(version) =
7601            read_package_installed_version(global_node_modules.clone(), package_name).await?
7602        {
7603            return Ok(Some((global_node_modules, version)));
7604        }
7605        return Ok(None);
7606    }
7607
7608    #[cfg(not(target_os = "windows"))]
7609    async fn which(&self, command: &OsStr) -> Option<PathBuf> {
7610        let worktree_abs_path = self.worktree.abs_path();
7611        let shell_path = self.shell_env().await.get("PATH").cloned();
7612        which::which_in(command, shell_path.as_ref(), worktree_abs_path).ok()
7613    }
7614
7615    #[cfg(target_os = "windows")]
7616    async fn which(&self, command: &OsStr) -> Option<PathBuf> {
7617        // todo(windows) Getting the shell env variables in a current directory on Windows is more complicated than other platforms
7618        //               there isn't a 'default shell' necessarily. The closest would be the default profile on the windows terminal
7619        //               SEE: https://learn.microsoft.com/en-us/windows/terminal/customize-settings/startup
7620        which::which(command).ok()
7621    }
7622
7623    async fn try_exec(&self, command: LanguageServerBinary) -> Result<()> {
7624        let working_dir = self.worktree_root_path();
7625        let output = smol::process::Command::new(&command.path)
7626            .args(command.arguments)
7627            .envs(command.env.clone().unwrap_or_default())
7628            .current_dir(working_dir)
7629            .output()
7630            .await?;
7631
7632        if output.status.success() {
7633            return Ok(());
7634        }
7635        Err(anyhow!(
7636            "{}, stdout: {:?}, stderr: {:?}",
7637            output.status,
7638            String::from_utf8_lossy(&output.stdout),
7639            String::from_utf8_lossy(&output.stderr)
7640        ))
7641    }
7642
7643    fn update_status(
7644        &self,
7645        server_name: LanguageServerName,
7646        status: language::LanguageServerBinaryStatus,
7647    ) {
7648        self.language_registry
7649            .update_lsp_status(server_name, status);
7650    }
7651
7652    async fn language_server_download_dir(&self, name: &LanguageServerName) -> Option<Arc<Path>> {
7653        let dir = self.language_registry.language_server_download_dir(name)?;
7654
7655        if !dir.exists() {
7656            smol::fs::create_dir_all(&dir)
7657                .await
7658                .context("failed to create container directory")
7659                .log_err()?;
7660        }
7661
7662        Some(dir)
7663    }
7664
7665    async fn read_text_file(&self, path: PathBuf) -> Result<String> {
7666        let entry = self
7667            .worktree
7668            .entry_for_path(&path)
7669            .with_context(|| format!("no worktree entry for path {path:?}"))?;
7670        let abs_path = self
7671            .worktree
7672            .absolutize(&entry.path)
7673            .with_context(|| format!("cannot absolutize path {path:?}"))?;
7674
7675        self.fs.load(&abs_path).await
7676    }
7677}
7678
7679async fn populate_labels_for_symbols(
7680    symbols: Vec<CoreSymbol>,
7681    language_registry: &Arc<LanguageRegistry>,
7682    default_language: Option<LanguageName>,
7683    lsp_adapter: Option<Arc<CachedLspAdapter>>,
7684    output: &mut Vec<Symbol>,
7685) {
7686    #[allow(clippy::mutable_key_type)]
7687    let mut symbols_by_language = HashMap::<Option<Arc<Language>>, Vec<CoreSymbol>>::default();
7688
7689    let mut unknown_path = None;
7690    for symbol in symbols {
7691        let language = language_registry
7692            .language_for_file_path(&symbol.path.path)
7693            .await
7694            .ok()
7695            .or_else(|| {
7696                unknown_path.get_or_insert(symbol.path.path.clone());
7697                default_language.as_ref().and_then(|name| {
7698                    language_registry
7699                        .language_for_name(&name.0)
7700                        .now_or_never()?
7701                        .ok()
7702                })
7703            });
7704        symbols_by_language
7705            .entry(language)
7706            .or_default()
7707            .push(symbol);
7708    }
7709
7710    if let Some(unknown_path) = unknown_path {
7711        log::info!(
7712            "no language found for symbol path {}",
7713            unknown_path.display()
7714        );
7715    }
7716
7717    let mut label_params = Vec::new();
7718    for (language, mut symbols) in symbols_by_language {
7719        label_params.clear();
7720        label_params.extend(
7721            symbols
7722                .iter_mut()
7723                .map(|symbol| (mem::take(&mut symbol.name), symbol.kind)),
7724        );
7725
7726        let mut labels = Vec::new();
7727        if let Some(language) = language {
7728            let lsp_adapter = lsp_adapter.clone().or_else(|| {
7729                language_registry
7730                    .lsp_adapters(&language.name())
7731                    .first()
7732                    .cloned()
7733            });
7734            if let Some(lsp_adapter) = lsp_adapter {
7735                labels = lsp_adapter
7736                    .labels_for_symbols(&label_params, &language)
7737                    .await
7738                    .log_err()
7739                    .unwrap_or_default();
7740            }
7741        }
7742
7743        for ((symbol, (name, _)), label) in symbols
7744            .into_iter()
7745            .zip(label_params.drain(..))
7746            .zip(labels.into_iter().chain(iter::repeat(None)))
7747        {
7748            output.push(Symbol {
7749                language_server_name: symbol.language_server_name,
7750                source_worktree_id: symbol.source_worktree_id,
7751                path: symbol.path,
7752                label: label.unwrap_or_else(|| CodeLabel::plain(name.clone(), None)),
7753                name,
7754                kind: symbol.kind,
7755                range: symbol.range,
7756                signature: symbol.signature,
7757            });
7758        }
7759    }
7760}
7761
7762fn include_text(server: &lsp::LanguageServer) -> Option<bool> {
7763    match server.capabilities().text_document_sync.as_ref()? {
7764        lsp::TextDocumentSyncCapability::Kind(kind) => match *kind {
7765            lsp::TextDocumentSyncKind::NONE => None,
7766            lsp::TextDocumentSyncKind::FULL => Some(true),
7767            lsp::TextDocumentSyncKind::INCREMENTAL => Some(false),
7768            _ => None,
7769        },
7770        lsp::TextDocumentSyncCapability::Options(options) => match options.save.as_ref()? {
7771            lsp::TextDocumentSyncSaveOptions::Supported(supported) => {
7772                if *supported {
7773                    Some(true)
7774                } else {
7775                    None
7776                }
7777            }
7778            lsp::TextDocumentSyncSaveOptions::SaveOptions(save_options) => {
7779                Some(save_options.include_text.unwrap_or(false))
7780            }
7781        },
7782    }
7783}
7784
7785#[cfg(test)]
7786#[test]
7787fn test_glob_literal_prefix() {
7788    assert_eq!(glob_literal_prefix("**/*.js"), "");
7789    assert_eq!(glob_literal_prefix("node_modules/**/*.js"), "node_modules");
7790    assert_eq!(glob_literal_prefix("foo/{bar,baz}.js"), "foo");
7791    assert_eq!(glob_literal_prefix("foo/bar/baz.js"), "foo/bar/baz.js");
7792}