lsp_store.rs

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