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