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