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