lsp_store.rs

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