lsp_store.rs

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