lsp_store.rs

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