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