Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T03:30:13.504Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

lsp_command.rs

5476 lines · 193.5 KB · rust
1pub mod signature_help;
2
3use crate::{
4    CodeAction, CompletionSource, CoreCompletion, CoreCompletionResponse, DocumentColor,
5    DocumentHighlight, DocumentSymbol, Hover, HoverBlock, HoverBlockKind, InlayHint,
6    InlayHintLabel, InlayHintLabelPart, InlayHintLabelPartTooltip, InlayHintTooltip, Location,
7    LocationLink, LspAction, LspPullDiagnostics, MarkupContent, PrepareRenameResponse, ProjectPath,
8    ProjectTransaction, PulledDiagnostics, ResolveState,
9    lsp_store::{LocalLspStore, LspDocumentLink, LspFoldingRange, LspStore},
10};
11use anyhow::{Context as _, Result};
12use async_trait::async_trait;
13use client::proto::{self, PeerId};
14use clock::Global;
15use collections::HashMap;
16use futures::future;
17use gpui::{App, AsyncApp, Entity, SharedString, Task, TaskExt, prelude::FluentBuilder};
18use language::{
19    Anchor, Bias, Buffer, BufferSnapshot, CachedLspAdapter, CharKind, CharScopeContext,
20    OffsetRangeExt, PointUtf16, ToOffset, ToPointUtf16, Transaction, Unclipped,
21    language_settings::{InlayHintKind, LanguageSettings},
22    lsp_to_symbol_kind, point_from_lsp, point_to_lsp,
23    proto::{
24        deserialize_anchor, deserialize_anchor_range, deserialize_version, serialize_anchor,
25        serialize_anchor_range, serialize_version,
26    },
27    range_from_lsp, range_to_lsp,
28};
29use lsp::{
30    AdapterServerCapabilities, CodeActionKind, CodeActionOptions, CodeDescription,
31    CompletionContext, CompletionListItemDefaultsEditRange, CompletionTriggerKind,
32    DocumentHighlightKind, LanguageServer, LanguageServerId, LinkedEditingRangeServerCapabilities,
33    OneOf, RenameOptions, ServerCapabilities,
34};
35use serde_json::Value;
36
37use signature_help::{lsp_to_proto_signature, proto_to_lsp_signature};
38use std::{cmp::Reverse, collections::hash_map, ops::Range, path::Path, str::FromStr, sync::Arc};
39use text::{BufferId, LineEnding};
40use util::rel_path::RelPath;
41use util::{ResultExt as _, debug_panic};
42
43pub use signature_help::SignatureHelp;
44
45fn code_action_kind_matches(requested: &lsp::CodeActionKind, actual: &lsp::CodeActionKind) -> bool {
46    let requested_str = requested.as_str();
47    let actual_str = actual.as_str();
48
49    // Exact match or hierarchical match
50    actual_str == requested_str
51        || actual_str
52            .strip_prefix(requested_str)
53            .is_some_and(|suffix| suffix.starts_with('.'))
54}
55
56pub fn lsp_formatting_options(settings: &LanguageSettings) -> lsp::FormattingOptions {
57    lsp::FormattingOptions {
58        tab_size: settings.tab_size.into(),
59        insert_spaces: !settings.hard_tabs,
60        trim_trailing_whitespace: Some(settings.remove_trailing_whitespace_on_save),
61        trim_final_newlines: Some(settings.ensure_final_newline_on_save),
62        insert_final_newline: Some(settings.ensure_final_newline_on_save),
63        ..lsp::FormattingOptions::default()
64    }
65}
66
67pub fn file_path_to_lsp_url(path: &Path) -> Result<lsp::Uri> {
68    match lsp::Uri::from_file_path(path) {
69        Ok(url) => Ok(url),
70        Err(()) => anyhow::bail!("Invalid file path provided to LSP request: {path:?}"),
71    }
72}
73
74pub(crate) fn make_text_document_identifier(path: &Path) -> Result<lsp::TextDocumentIdentifier> {
75    Ok(lsp::TextDocumentIdentifier {
76        uri: file_path_to_lsp_url(path)?,
77    })
78}
79
80pub(crate) fn make_lsp_text_document_position(
81    path: &Path,
82    position: PointUtf16,
83) -> Result<lsp::TextDocumentPositionParams> {
84    Ok(lsp::TextDocumentPositionParams {
85        text_document: make_text_document_identifier(path)?,
86        position: point_to_lsp(position),
87    })
88}
89
90#[async_trait(?Send)]
91pub trait LspCommand: 'static + Sized + Send + std::fmt::Debug {
92    type Response: 'static + Default + Send + std::fmt::Debug;
93    type LspRequest: 'static + Send + lsp::request::Request;
94    type ProtoRequest: 'static + Send + proto::RequestMessage;
95
96    fn display_name(&self) -> &str;
97
98    fn status(&self) -> Option<String> {
99        None
100    }
101
102    fn to_lsp_params_or_response(
103        &self,
104        path: &Path,
105        buffer: &Buffer,
106        language_server: &Arc<LanguageServer>,
107        cx: &App,
108    ) -> Result<
109        LspParamsOrResponse<<Self::LspRequest as lsp::request::Request>::Params, Self::Response>,
110    > {
111        if self.check_capabilities(language_server.adapter_server_capabilities()) {
112            Ok(LspParamsOrResponse::Params(self.to_lsp(
113                path,
114                buffer,
115                language_server,
116                cx,
117            )?))
118        } else {
119            Ok(LspParamsOrResponse::Response(Default::default()))
120        }
121    }
122
123    /// When false, `to_lsp_params_or_response` default implementation will return the default response.
124    fn check_capabilities(&self, _: AdapterServerCapabilities) -> bool;
125
126    fn to_lsp(
127        &self,
128        path: &Path,
129        buffer: &Buffer,
130        language_server: &Arc<LanguageServer>,
131        cx: &App,
132    ) -> Result<<Self::LspRequest as lsp::request::Request>::Params>;
133
134    async fn response_from_lsp(
135        self,
136        message: <Self::LspRequest as lsp::request::Request>::Result,
137        lsp_store: Entity<LspStore>,
138        buffer: Entity<Buffer>,
139        server_id: LanguageServerId,
140        cx: AsyncApp,
141    ) -> Result<Self::Response>;
142
143    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest;
144
145    async fn from_proto(
146        message: Self::ProtoRequest,
147        lsp_store: Entity<LspStore>,
148        buffer: Entity<Buffer>,
149        cx: AsyncApp,
150    ) -> Result<Self>;
151
152    fn response_to_proto(
153        response: Self::Response,
154        lsp_store: &mut LspStore,
155        peer_id: PeerId,
156        buffer_version: &clock::Global,
157        cx: &mut App,
158    ) -> <Self::ProtoRequest as proto::RequestMessage>::Response;
159
160    async fn response_from_proto(
161        self,
162        message: <Self::ProtoRequest as proto::RequestMessage>::Response,
163        lsp_store: Entity<LspStore>,
164        buffer: Entity<Buffer>,
165        cx: AsyncApp,
166    ) -> Result<Self::Response>;
167
168    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId>;
169}
170
171pub enum LspParamsOrResponse<P, R> {
172    Params(P),
173    Response(R),
174}
175
176#[derive(Debug)]
177pub(crate) struct PrepareRename {
178    pub position: PointUtf16,
179}
180
181#[derive(Debug)]
182pub(crate) struct PerformRename {
183    pub position: PointUtf16,
184    pub new_name: String,
185    pub push_to_history: bool,
186}
187
188#[derive(Debug, Clone, Copy)]
189pub struct GetDefinitions {
190    pub position: PointUtf16,
191}
192
193#[derive(Debug, Clone, PartialEq, Eq, Hash)]
194pub struct EditPredictionDefinition {
195    pub path: ProjectPath,
196    pub range: Range<Unclipped<PointUtf16>>,
197}
198
199#[derive(Debug, Clone, Copy)]
200pub(crate) struct GetEditPredictionDefinitions {
201    pub position: PointUtf16,
202}
203
204#[derive(Debug, Clone, Copy)]
205pub(crate) struct GetDeclarations {
206    pub position: PointUtf16,
207}
208
209#[derive(Debug, Clone, Copy)]
210pub(crate) struct GetTypeDefinitions {
211    pub position: PointUtf16,
212}
213
214#[derive(Debug, Clone, Copy)]
215pub(crate) struct GetEditPredictionTypeDefinitions {
216    pub position: PointUtf16,
217}
218
219#[derive(Debug, Clone, Copy)]
220pub(crate) struct GetImplementations {
221    pub position: PointUtf16,
222}
223
224#[derive(Debug, Clone, Copy)]
225pub(crate) struct GetReferences {
226    pub position: PointUtf16,
227}
228
229#[derive(Debug)]
230pub(crate) struct GetDocumentHighlights {
231    pub position: PointUtf16,
232}
233
234#[derive(Debug, Copy, Clone)]
235pub(crate) struct GetDocumentSymbols;
236
237#[derive(Clone, Debug)]
238pub(crate) struct GetSignatureHelp {
239    pub position: PointUtf16,
240}
241
242#[derive(Clone, Debug)]
243pub(crate) struct GetHover {
244    pub position: PointUtf16,
245}
246
247#[derive(Debug)]
248pub(crate) struct GetCompletions {
249    pub position: PointUtf16,
250    pub context: CompletionContext,
251    pub server_id: Option<lsp::LanguageServerId>,
252}
253
254#[derive(Clone, Debug)]
255pub(crate) struct GetCodeActions {
256    pub range: Range<Anchor>,
257    pub kinds: Option<Vec<lsp::CodeActionKind>>,
258}
259
260#[derive(Debug)]
261pub(crate) struct OnTypeFormatting {
262    pub position: PointUtf16,
263    pub trigger: String,
264    pub options: lsp::FormattingOptions,
265    pub push_to_history: bool,
266}
267
268#[derive(Clone, Debug)]
269pub(crate) struct InlayHints {
270    pub range: Range<Anchor>,
271}
272
273#[derive(Debug, Clone, Copy)]
274pub(crate) struct SemanticTokensFull {
275    pub for_server: Option<LanguageServerId>,
276}
277
278#[derive(Debug, Clone)]
279pub(crate) struct SemanticTokensDelta {
280    pub previous_result_id: SharedString,
281}
282
283#[derive(Debug)]
284pub(crate) enum SemanticTokensResponse {
285    Full {
286        data: Vec<u32>,
287        result_id: Option<SharedString>,
288    },
289    Delta {
290        edits: Vec<SemanticTokensEdit>,
291        result_id: Option<SharedString>,
292    },
293}
294
295impl Default for SemanticTokensResponse {
296    fn default() -> Self {
297        Self::Delta {
298            edits: Vec::new(),
299            result_id: None,
300        }
301    }
302}
303
304#[derive(Debug)]
305pub(crate) struct SemanticTokensEdit {
306    pub start: u32,
307    pub delete_count: u32,
308    pub data: Vec<u32>,
309}
310
311#[derive(Debug, Copy, Clone)]
312pub(crate) struct GetCodeLens;
313
314#[derive(Debug, Copy, Clone)]
315pub(crate) struct GetDocumentColor;
316
317#[derive(Debug, Copy, Clone)]
318pub(crate) struct GetFoldingRanges;
319
320#[derive(Debug, Copy, Clone)]
321pub(crate) struct GetDocumentLinks;
322
323impl GetCodeLens {
324    pub(crate) fn can_resolve_lens(capabilities: &ServerCapabilities) -> bool {
325        capabilities
326            .code_lens_provider
327            .as_ref()
328            .and_then(|code_lens_options| code_lens_options.resolve_provider)
329            .unwrap_or(false)
330    }
331}
332
333#[derive(Debug)]
334pub(crate) struct LinkedEditingRange {
335    pub position: Anchor,
336}
337
338#[derive(Clone, Debug)]
339pub struct GetDocumentDiagnostics {
340    /// We cannot blindly rely on server's capabilities.diagnostic_provider, as they're a singular field, whereas
341    /// a server can register multiple diagnostic providers post-mortem.
342    pub registration_id: Option<SharedString>,
343    pub identifier: Option<SharedString>,
344    pub previous_result_id: Option<SharedString>,
345}
346
347#[async_trait(?Send)]
348impl LspCommand for PrepareRename {
349    type Response = PrepareRenameResponse;
350    type LspRequest = lsp::request::PrepareRenameRequest;
351    type ProtoRequest = proto::PrepareRename;
352
353    fn display_name(&self) -> &str {
354        "Prepare rename"
355    }
356
357    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
358        capabilities
359            .server_capabilities
360            .rename_provider
361            .is_some_and(|capability| match capability {
362                OneOf::Left(enabled) => enabled,
363                OneOf::Right(options) => options.prepare_provider.unwrap_or(false),
364            })
365    }
366
367    fn to_lsp_params_or_response(
368        &self,
369        path: &Path,
370        buffer: &Buffer,
371        language_server: &Arc<LanguageServer>,
372        cx: &App,
373    ) -> Result<LspParamsOrResponse<lsp::TextDocumentPositionParams, PrepareRenameResponse>> {
374        let rename_provider = language_server
375            .adapter_server_capabilities()
376            .server_capabilities
377            .rename_provider;
378        match rename_provider {
379            Some(lsp::OneOf::Right(RenameOptions {
380                prepare_provider: Some(true),
381                ..
382            })) => Ok(LspParamsOrResponse::Params(self.to_lsp(
383                path,
384                buffer,
385                language_server,
386                cx,
387            )?)),
388            Some(lsp::OneOf::Right(_)) => Ok(LspParamsOrResponse::Response(
389                PrepareRenameResponse::OnlyUnpreparedRenameSupported,
390            )),
391            Some(lsp::OneOf::Left(true)) => Ok(LspParamsOrResponse::Response(
392                PrepareRenameResponse::OnlyUnpreparedRenameSupported,
393            )),
394            _ => anyhow::bail!("Rename not supported"),
395        }
396    }
397
398    fn to_lsp(
399        &self,
400        path: &Path,
401        _: &Buffer,
402        _: &Arc<LanguageServer>,
403        _: &App,
404    ) -> Result<lsp::TextDocumentPositionParams> {
405        make_lsp_text_document_position(path, self.position)
406    }
407
408    async fn response_from_lsp(
409        self,
410        message: Option<lsp::PrepareRenameResponse>,
411        _: Entity<LspStore>,
412        buffer: Entity<Buffer>,
413        _: LanguageServerId,
414        cx: AsyncApp,
415    ) -> Result<PrepareRenameResponse> {
416        buffer.read_with(&cx, |buffer, _| match message {
417            Some(lsp::PrepareRenameResponse::Range(range))
418            | Some(lsp::PrepareRenameResponse::RangeWithPlaceholder { range, .. }) => {
419                let Range { start, end } = range_from_lsp(range);
420                if buffer.clip_point_utf16(start, Bias::Left) == start.0
421                    && buffer.clip_point_utf16(end, Bias::Left) == end.0
422                {
423                    Ok(PrepareRenameResponse::Success(
424                        buffer.anchor_after(start)..buffer.anchor_before(end),
425                    ))
426                } else {
427                    Ok(PrepareRenameResponse::InvalidPosition)
428                }
429            }
430            Some(lsp::PrepareRenameResponse::DefaultBehavior { .. }) => {
431                let snapshot = buffer.snapshot();
432                let (range, _) = snapshot.surrounding_word(self.position, None);
433                let range = snapshot.anchor_after(range.start)..snapshot.anchor_before(range.end);
434                Ok(PrepareRenameResponse::Success(range))
435            }
436            None => Ok(PrepareRenameResponse::InvalidPosition),
437        })
438    }
439
440    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::PrepareRename {
441        proto::PrepareRename {
442            project_id,
443            buffer_id: buffer.remote_id().into(),
444            position: Some(language::proto::serialize_anchor(
445                &buffer.anchor_before(self.position),
446            )),
447            version: serialize_version(&buffer.version()),
448        }
449    }
450
451    async fn from_proto(
452        message: proto::PrepareRename,
453        _: Entity<LspStore>,
454        buffer: Entity<Buffer>,
455        mut cx: AsyncApp,
456    ) -> Result<Self> {
457        let position = message
458            .position
459            .and_then(deserialize_anchor)
460            .context("invalid position")?;
461        buffer
462            .update(&mut cx, |buffer, _| {
463                buffer.wait_for_version(deserialize_version(&message.version))
464            })
465            .await?;
466
467        Ok(Self {
468            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
469        })
470    }
471
472    fn response_to_proto(
473        response: PrepareRenameResponse,
474        _: &mut LspStore,
475        _: PeerId,
476        buffer_version: &clock::Global,
477        _: &mut App,
478    ) -> proto::PrepareRenameResponse {
479        match response {
480            PrepareRenameResponse::Success(range) => proto::PrepareRenameResponse {
481                can_rename: true,
482                only_unprepared_rename_supported: false,
483                start: Some(language::proto::serialize_anchor(&range.start)),
484                end: Some(language::proto::serialize_anchor(&range.end)),
485                version: serialize_version(buffer_version),
486            },
487            PrepareRenameResponse::OnlyUnpreparedRenameSupported => proto::PrepareRenameResponse {
488                can_rename: false,
489                only_unprepared_rename_supported: true,
490                start: None,
491                end: None,
492                version: vec![],
493            },
494            PrepareRenameResponse::InvalidPosition => proto::PrepareRenameResponse {
495                can_rename: false,
496                only_unprepared_rename_supported: false,
497                start: None,
498                end: None,
499                version: vec![],
500            },
501        }
502    }
503
504    async fn response_from_proto(
505        self,
506        message: proto::PrepareRenameResponse,
507        _: Entity<LspStore>,
508        buffer: Entity<Buffer>,
509        mut cx: AsyncApp,
510    ) -> Result<PrepareRenameResponse> {
511        if message.can_rename {
512            buffer
513                .update(&mut cx, |buffer, _| {
514                    buffer.wait_for_version(deserialize_version(&message.version))
515                })
516                .await?;
517            if let (Some(start), Some(end)) = (
518                message.start.and_then(deserialize_anchor),
519                message.end.and_then(deserialize_anchor),
520            ) {
521                Ok(PrepareRenameResponse::Success(start..end))
522            } else {
523                anyhow::bail!(
524                    "Missing start or end position in remote project PrepareRenameResponse"
525                );
526            }
527        } else if message.only_unprepared_rename_supported {
528            Ok(PrepareRenameResponse::OnlyUnpreparedRenameSupported)
529        } else {
530            Ok(PrepareRenameResponse::InvalidPosition)
531        }
532    }
533
534    fn buffer_id_from_proto(message: &proto::PrepareRename) -> Result<BufferId> {
535        BufferId::new(message.buffer_id)
536    }
537}
538
539#[async_trait(?Send)]
540impl LspCommand for PerformRename {
541    type Response = ProjectTransaction;
542    type LspRequest = lsp::request::Rename;
543    type ProtoRequest = proto::PerformRename;
544
545    fn display_name(&self) -> &str {
546        "Rename"
547    }
548
549    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
550        capabilities
551            .server_capabilities
552            .rename_provider
553            .is_some_and(|capability| match capability {
554                OneOf::Left(enabled) => enabled,
555                OneOf::Right(_) => true,
556            })
557    }
558
559    fn to_lsp(
560        &self,
561        path: &Path,
562        _: &Buffer,
563        _: &Arc<LanguageServer>,
564        _: &App,
565    ) -> Result<lsp::RenameParams> {
566        Ok(lsp::RenameParams {
567            text_document_position: make_lsp_text_document_position(path, self.position)?,
568            new_name: self.new_name.clone(),
569            work_done_progress_params: Default::default(),
570        })
571    }
572
573    async fn response_from_lsp(
574        self,
575        message: Option<lsp::WorkspaceEdit>,
576        lsp_store: Entity<LspStore>,
577        buffer: Entity<Buffer>,
578        server_id: LanguageServerId,
579        mut cx: AsyncApp,
580    ) -> Result<ProjectTransaction> {
581        if let Some(edit) = message {
582            let (_, lsp_server) =
583                language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
584            LocalLspStore::deserialize_workspace_edit(
585                lsp_store,
586                edit,
587                self.push_to_history,
588                lsp_server,
589                &mut cx,
590            )
591            .await
592        } else {
593            Ok(ProjectTransaction::default())
594        }
595    }
596
597    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::PerformRename {
598        proto::PerformRename {
599            project_id,
600            buffer_id: buffer.remote_id().into(),
601            position: Some(language::proto::serialize_anchor(
602                &buffer.anchor_before(self.position),
603            )),
604            new_name: self.new_name.clone(),
605            version: serialize_version(&buffer.version()),
606        }
607    }
608
609    async fn from_proto(
610        message: proto::PerformRename,
611        _: Entity<LspStore>,
612        buffer: Entity<Buffer>,
613        mut cx: AsyncApp,
614    ) -> Result<Self> {
615        let position = message
616            .position
617            .and_then(deserialize_anchor)
618            .context("invalid position")?;
619        buffer
620            .update(&mut cx, |buffer, _| {
621                buffer.wait_for_version(deserialize_version(&message.version))
622            })
623            .await?;
624        Ok(Self {
625            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
626            new_name: message.new_name,
627            push_to_history: false,
628        })
629    }
630
631    fn response_to_proto(
632        response: ProjectTransaction,
633        lsp_store: &mut LspStore,
634        peer_id: PeerId,
635        _: &clock::Global,
636        cx: &mut App,
637    ) -> proto::PerformRenameResponse {
638        let transaction = lsp_store.buffer_store().update(cx, |buffer_store, cx| {
639            buffer_store.serialize_project_transaction_for_peer(response, peer_id, cx)
640        });
641        proto::PerformRenameResponse {
642            transaction: Some(transaction),
643        }
644    }
645
646    async fn response_from_proto(
647        self,
648        message: proto::PerformRenameResponse,
649        lsp_store: Entity<LspStore>,
650        _: Entity<Buffer>,
651        mut cx: AsyncApp,
652    ) -> Result<ProjectTransaction> {
653        let message = message.transaction.context("missing transaction")?;
654        lsp_store
655            .update(&mut cx, |lsp_store, cx| {
656                lsp_store.buffer_store().update(cx, |buffer_store, cx| {
657                    buffer_store.deserialize_project_transaction(message, self.push_to_history, cx)
658                })
659            })
660            .await
661    }
662
663    fn buffer_id_from_proto(message: &proto::PerformRename) -> Result<BufferId> {
664        BufferId::new(message.buffer_id)
665    }
666}
667
668#[async_trait(?Send)]
669impl LspCommand for GetDefinitions {
670    type Response = Vec<LocationLink>;
671    type LspRequest = lsp::request::GotoDefinition;
672    type ProtoRequest = proto::GetDefinition;
673
674    fn display_name(&self) -> &str {
675        "Get definition"
676    }
677
678    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
679        capabilities
680            .server_capabilities
681            .definition_provider
682            .is_some_and(|capability| match capability {
683                OneOf::Left(supported) => supported,
684                OneOf::Right(_options) => true,
685            })
686    }
687
688    fn to_lsp(
689        &self,
690        path: &Path,
691        _: &Buffer,
692        _: &Arc<LanguageServer>,
693        _: &App,
694    ) -> Result<lsp::GotoDefinitionParams> {
695        Ok(lsp::GotoDefinitionParams {
696            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
697            work_done_progress_params: Default::default(),
698            partial_result_params: Default::default(),
699        })
700    }
701
702    async fn response_from_lsp(
703        self,
704        message: Option<lsp::GotoDefinitionResponse>,
705        lsp_store: Entity<LspStore>,
706        buffer: Entity<Buffer>,
707        server_id: LanguageServerId,
708        cx: AsyncApp,
709    ) -> Result<Vec<LocationLink>> {
710        location_links_from_lsp(message, lsp_store, buffer, server_id, cx).await
711    }
712
713    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDefinition {
714        proto::GetDefinition {
715            project_id,
716            buffer_id: buffer.remote_id().into(),
717            position: Some(language::proto::serialize_anchor(
718                &buffer.anchor_before(self.position),
719            )),
720            version: serialize_version(&buffer.version()),
721        }
722    }
723
724    async fn from_proto(
725        message: proto::GetDefinition,
726        _: Entity<LspStore>,
727        buffer: Entity<Buffer>,
728        mut cx: AsyncApp,
729    ) -> Result<Self> {
730        let position = message
731            .position
732            .and_then(deserialize_anchor)
733            .context("invalid position")?;
734        buffer
735            .update(&mut cx, |buffer, _| {
736                buffer.wait_for_version(deserialize_version(&message.version))
737            })
738            .await?;
739        Ok(Self {
740            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
741        })
742    }
743
744    fn response_to_proto(
745        response: Vec<LocationLink>,
746        lsp_store: &mut LspStore,
747        peer_id: PeerId,
748        _: &clock::Global,
749        cx: &mut App,
750    ) -> proto::GetDefinitionResponse {
751        let links = location_links_to_proto(response, lsp_store, peer_id, cx);
752        proto::GetDefinitionResponse { links }
753    }
754
755    async fn response_from_proto(
756        self,
757        message: proto::GetDefinitionResponse,
758        lsp_store: Entity<LspStore>,
759        _: Entity<Buffer>,
760        cx: AsyncApp,
761    ) -> Result<Vec<LocationLink>> {
762        location_links_from_proto(message.links, lsp_store, cx).await
763    }
764
765    fn buffer_id_from_proto(message: &proto::GetDefinition) -> Result<BufferId> {
766        BufferId::new(message.buffer_id)
767    }
768}
769
770#[async_trait(?Send)]
771impl LspCommand for GetEditPredictionDefinitions {
772    type Response = Vec<EditPredictionDefinition>;
773    type LspRequest = lsp::request::GotoDefinition;
774    type ProtoRequest = proto::GetEditPredictionDefinition;
775
776    fn display_name(&self) -> &str {
777        "Get edit prediction definition"
778    }
779
780    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
781        capabilities
782            .server_capabilities
783            .definition_provider
784            .is_some_and(|capability| match capability {
785                OneOf::Left(supported) => supported,
786                OneOf::Right(_options) => true,
787            })
788    }
789
790    fn to_lsp(
791        &self,
792        path: &Path,
793        _: &Buffer,
794        _: &Arc<LanguageServer>,
795        _: &App,
796    ) -> Result<lsp::GotoDefinitionParams> {
797        Ok(lsp::GotoDefinitionParams {
798            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
799            work_done_progress_params: Default::default(),
800            partial_result_params: Default::default(),
801        })
802    }
803
804    async fn response_from_lsp(
805        self,
806        message: Option<lsp::GotoDefinitionResponse>,
807        lsp_store: Entity<LspStore>,
808        _: Entity<Buffer>,
809        _: LanguageServerId,
810        cx: AsyncApp,
811    ) -> Result<Vec<EditPredictionDefinition>> {
812        edit_prediction_definitions_from_lsp(message, lsp_store, cx)
813    }
814
815    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetEditPredictionDefinition {
816        proto::GetEditPredictionDefinition {
817            project_id,
818            buffer_id: buffer.remote_id().into(),
819            position: Some(language::proto::serialize_anchor(
820                &buffer.anchor_before(self.position),
821            )),
822            version: serialize_version(&buffer.version()),
823        }
824    }
825
826    async fn from_proto(
827        message: proto::GetEditPredictionDefinition,
828        _: Entity<LspStore>,
829        buffer: Entity<Buffer>,
830        mut cx: AsyncApp,
831    ) -> Result<Self> {
832        Ok(Self {
833            position: edit_prediction_position_from_proto(
834                message.position,
835                message.version,
836                buffer,
837                &mut cx,
838            )
839            .await?,
840        })
841    }
842
843    fn response_to_proto(
844        response: Vec<EditPredictionDefinition>,
845        _: &mut LspStore,
846        _: PeerId,
847        _: &clock::Global,
848        _: &mut App,
849    ) -> proto::GetEditPredictionDefinitionResponse {
850        proto::GetEditPredictionDefinitionResponse {
851            definitions: edit_prediction_definitions_to_proto(response),
852        }
853    }
854
855    async fn response_from_proto(
856        self,
857        message: proto::GetEditPredictionDefinitionResponse,
858        _: Entity<LspStore>,
859        _: Entity<Buffer>,
860        _: AsyncApp,
861    ) -> Result<Vec<EditPredictionDefinition>> {
862        edit_prediction_definitions_from_proto(message.definitions)
863    }
864
865    fn buffer_id_from_proto(message: &proto::GetEditPredictionDefinition) -> Result<BufferId> {
866        BufferId::new(message.buffer_id)
867    }
868}
869
870#[async_trait(?Send)]
871impl LspCommand for GetDeclarations {
872    type Response = Vec<LocationLink>;
873    type LspRequest = lsp::request::GotoDeclaration;
874    type ProtoRequest = proto::GetDeclaration;
875
876    fn display_name(&self) -> &str {
877        "Get declaration"
878    }
879
880    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
881        capabilities
882            .server_capabilities
883            .declaration_provider
884            .is_some_and(|capability| match capability {
885                lsp::DeclarationCapability::Simple(supported) => supported,
886                lsp::DeclarationCapability::RegistrationOptions(..) => true,
887                lsp::DeclarationCapability::Options(..) => true,
888            })
889    }
890
891    fn to_lsp(
892        &self,
893        path: &Path,
894        _: &Buffer,
895        _: &Arc<LanguageServer>,
896        _: &App,
897    ) -> Result<lsp::GotoDeclarationParams> {
898        Ok(lsp::GotoDeclarationParams {
899            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
900            work_done_progress_params: Default::default(),
901            partial_result_params: Default::default(),
902        })
903    }
904
905    async fn response_from_lsp(
906        self,
907        message: Option<lsp::GotoDeclarationResponse>,
908        lsp_store: Entity<LspStore>,
909        buffer: Entity<Buffer>,
910        server_id: LanguageServerId,
911        cx: AsyncApp,
912    ) -> Result<Vec<LocationLink>> {
913        location_links_from_lsp(message, lsp_store, buffer, server_id, cx).await
914    }
915
916    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDeclaration {
917        proto::GetDeclaration {
918            project_id,
919            buffer_id: buffer.remote_id().into(),
920            position: Some(language::proto::serialize_anchor(
921                &buffer.anchor_before(self.position),
922            )),
923            version: serialize_version(&buffer.version()),
924        }
925    }
926
927    async fn from_proto(
928        message: proto::GetDeclaration,
929        _: Entity<LspStore>,
930        buffer: Entity<Buffer>,
931        mut cx: AsyncApp,
932    ) -> Result<Self> {
933        let position = message
934            .position
935            .and_then(deserialize_anchor)
936            .context("invalid position")?;
937        buffer
938            .update(&mut cx, |buffer, _| {
939                buffer.wait_for_version(deserialize_version(&message.version))
940            })
941            .await?;
942        Ok(Self {
943            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
944        })
945    }
946
947    fn response_to_proto(
948        response: Vec<LocationLink>,
949        lsp_store: &mut LspStore,
950        peer_id: PeerId,
951        _: &clock::Global,
952        cx: &mut App,
953    ) -> proto::GetDeclarationResponse {
954        let links = location_links_to_proto(response, lsp_store, peer_id, cx);
955        proto::GetDeclarationResponse { links }
956    }
957
958    async fn response_from_proto(
959        self,
960        message: proto::GetDeclarationResponse,
961        lsp_store: Entity<LspStore>,
962        _: Entity<Buffer>,
963        cx: AsyncApp,
964    ) -> Result<Vec<LocationLink>> {
965        location_links_from_proto(message.links, lsp_store, cx).await
966    }
967
968    fn buffer_id_from_proto(message: &proto::GetDeclaration) -> Result<BufferId> {
969        BufferId::new(message.buffer_id)
970    }
971}
972
973#[async_trait(?Send)]
974impl LspCommand for GetImplementations {
975    type Response = Vec<LocationLink>;
976    type LspRequest = lsp::request::GotoImplementation;
977    type ProtoRequest = proto::GetImplementation;
978
979    fn display_name(&self) -> &str {
980        "Get implementation"
981    }
982
983    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
984        capabilities
985            .server_capabilities
986            .implementation_provider
987            .is_some_and(|capability| match capability {
988                lsp::ImplementationProviderCapability::Simple(enabled) => enabled,
989                lsp::ImplementationProviderCapability::Options(_options) => true,
990            })
991    }
992
993    fn to_lsp(
994        &self,
995        path: &Path,
996        _: &Buffer,
997        _: &Arc<LanguageServer>,
998        _: &App,
999    ) -> Result<lsp::GotoImplementationParams> {
1000        Ok(lsp::GotoImplementationParams {
1001            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
1002            work_done_progress_params: Default::default(),
1003            partial_result_params: Default::default(),
1004        })
1005    }
1006
1007    async fn response_from_lsp(
1008        self,
1009        message: Option<lsp::GotoImplementationResponse>,
1010        lsp_store: Entity<LspStore>,
1011        buffer: Entity<Buffer>,
1012        server_id: LanguageServerId,
1013        cx: AsyncApp,
1014    ) -> Result<Vec<LocationLink>> {
1015        location_links_from_lsp(message, lsp_store, buffer, server_id, cx).await
1016    }
1017
1018    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetImplementation {
1019        proto::GetImplementation {
1020            project_id,
1021            buffer_id: buffer.remote_id().into(),
1022            position: Some(language::proto::serialize_anchor(
1023                &buffer.anchor_before(self.position),
1024            )),
1025            version: serialize_version(&buffer.version()),
1026        }
1027    }
1028
1029    async fn from_proto(
1030        message: proto::GetImplementation,
1031        _: Entity<LspStore>,
1032        buffer: Entity<Buffer>,
1033        mut cx: AsyncApp,
1034    ) -> Result<Self> {
1035        let position = message
1036            .position
1037            .and_then(deserialize_anchor)
1038            .context("invalid position")?;
1039        buffer
1040            .update(&mut cx, |buffer, _| {
1041                buffer.wait_for_version(deserialize_version(&message.version))
1042            })
1043            .await?;
1044        Ok(Self {
1045            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
1046        })
1047    }
1048
1049    fn response_to_proto(
1050        response: Vec<LocationLink>,
1051        lsp_store: &mut LspStore,
1052        peer_id: PeerId,
1053        _: &clock::Global,
1054        cx: &mut App,
1055    ) -> proto::GetImplementationResponse {
1056        let links = location_links_to_proto(response, lsp_store, peer_id, cx);
1057        proto::GetImplementationResponse { links }
1058    }
1059
1060    async fn response_from_proto(
1061        self,
1062        message: proto::GetImplementationResponse,
1063        project: Entity<LspStore>,
1064        _: Entity<Buffer>,
1065        cx: AsyncApp,
1066    ) -> Result<Vec<LocationLink>> {
1067        location_links_from_proto(message.links, project, cx).await
1068    }
1069
1070    fn buffer_id_from_proto(message: &proto::GetImplementation) -> Result<BufferId> {
1071        BufferId::new(message.buffer_id)
1072    }
1073}
1074
1075#[async_trait(?Send)]
1076impl LspCommand for GetTypeDefinitions {
1077    type Response = Vec<LocationLink>;
1078    type LspRequest = lsp::request::GotoTypeDefinition;
1079    type ProtoRequest = proto::GetTypeDefinition;
1080
1081    fn display_name(&self) -> &str {
1082        "Get type definition"
1083    }
1084
1085    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1086        !matches!(
1087            &capabilities.server_capabilities.type_definition_provider,
1088            None | Some(lsp::TypeDefinitionProviderCapability::Simple(false))
1089        )
1090    }
1091
1092    fn to_lsp(
1093        &self,
1094        path: &Path,
1095        _: &Buffer,
1096        _: &Arc<LanguageServer>,
1097        _: &App,
1098    ) -> Result<lsp::GotoTypeDefinitionParams> {
1099        Ok(lsp::GotoTypeDefinitionParams {
1100            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
1101            work_done_progress_params: Default::default(),
1102            partial_result_params: Default::default(),
1103        })
1104    }
1105
1106    async fn response_from_lsp(
1107        self,
1108        message: Option<lsp::GotoTypeDefinitionResponse>,
1109        project: Entity<LspStore>,
1110        buffer: Entity<Buffer>,
1111        server_id: LanguageServerId,
1112        cx: AsyncApp,
1113    ) -> Result<Vec<LocationLink>> {
1114        location_links_from_lsp(message, project, buffer, server_id, cx).await
1115    }
1116
1117    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetTypeDefinition {
1118        proto::GetTypeDefinition {
1119            project_id,
1120            buffer_id: buffer.remote_id().into(),
1121            position: Some(language::proto::serialize_anchor(
1122                &buffer.anchor_before(self.position),
1123            )),
1124            version: serialize_version(&buffer.version()),
1125        }
1126    }
1127
1128    async fn from_proto(
1129        message: proto::GetTypeDefinition,
1130        _: Entity<LspStore>,
1131        buffer: Entity<Buffer>,
1132        mut cx: AsyncApp,
1133    ) -> Result<Self> {
1134        let position = message
1135            .position
1136            .and_then(deserialize_anchor)
1137            .context("invalid position")?;
1138        buffer
1139            .update(&mut cx, |buffer, _| {
1140                buffer.wait_for_version(deserialize_version(&message.version))
1141            })
1142            .await?;
1143        Ok(Self {
1144            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
1145        })
1146    }
1147
1148    fn response_to_proto(
1149        response: Vec<LocationLink>,
1150        lsp_store: &mut LspStore,
1151        peer_id: PeerId,
1152        _: &clock::Global,
1153        cx: &mut App,
1154    ) -> proto::GetTypeDefinitionResponse {
1155        let links = location_links_to_proto(response, lsp_store, peer_id, cx);
1156        proto::GetTypeDefinitionResponse { links }
1157    }
1158
1159    async fn response_from_proto(
1160        self,
1161        message: proto::GetTypeDefinitionResponse,
1162        project: Entity<LspStore>,
1163        _: Entity<Buffer>,
1164        cx: AsyncApp,
1165    ) -> Result<Vec<LocationLink>> {
1166        location_links_from_proto(message.links, project, cx).await
1167    }
1168
1169    fn buffer_id_from_proto(message: &proto::GetTypeDefinition) -> Result<BufferId> {
1170        BufferId::new(message.buffer_id)
1171    }
1172}
1173
1174#[async_trait(?Send)]
1175impl LspCommand for GetEditPredictionTypeDefinitions {
1176    type Response = Vec<EditPredictionDefinition>;
1177    type LspRequest = lsp::request::GotoTypeDefinition;
1178    type ProtoRequest = proto::GetEditPredictionTypeDefinition;
1179
1180    fn display_name(&self) -> &str {
1181        "Get edit prediction type definition"
1182    }
1183
1184    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1185        !matches!(
1186            &capabilities.server_capabilities.type_definition_provider,
1187            None | Some(lsp::TypeDefinitionProviderCapability::Simple(false))
1188        )
1189    }
1190
1191    fn to_lsp(
1192        &self,
1193        path: &Path,
1194        _: &Buffer,
1195        _: &Arc<LanguageServer>,
1196        _: &App,
1197    ) -> Result<lsp::GotoTypeDefinitionParams> {
1198        Ok(lsp::GotoTypeDefinitionParams {
1199            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
1200            work_done_progress_params: Default::default(),
1201            partial_result_params: Default::default(),
1202        })
1203    }
1204
1205    async fn response_from_lsp(
1206        self,
1207        message: Option<lsp::GotoDefinitionResponse>,
1208        lsp_store: Entity<LspStore>,
1209        _: Entity<Buffer>,
1210        _: LanguageServerId,
1211        cx: AsyncApp,
1212    ) -> Result<Vec<EditPredictionDefinition>> {
1213        edit_prediction_definitions_from_lsp(message, lsp_store, cx)
1214    }
1215
1216    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetEditPredictionTypeDefinition {
1217        proto::GetEditPredictionTypeDefinition {
1218            project_id,
1219            buffer_id: buffer.remote_id().into(),
1220            position: Some(language::proto::serialize_anchor(
1221                &buffer.anchor_before(self.position),
1222            )),
1223            version: serialize_version(&buffer.version()),
1224        }
1225    }
1226
1227    async fn from_proto(
1228        message: proto::GetEditPredictionTypeDefinition,
1229        _: Entity<LspStore>,
1230        buffer: Entity<Buffer>,
1231        mut cx: AsyncApp,
1232    ) -> Result<Self> {
1233        Ok(Self {
1234            position: edit_prediction_position_from_proto(
1235                message.position,
1236                message.version,
1237                buffer,
1238                &mut cx,
1239            )
1240            .await?,
1241        })
1242    }
1243
1244    fn response_to_proto(
1245        response: Vec<EditPredictionDefinition>,
1246        _: &mut LspStore,
1247        _: PeerId,
1248        _: &clock::Global,
1249        _: &mut App,
1250    ) -> proto::GetEditPredictionTypeDefinitionResponse {
1251        proto::GetEditPredictionTypeDefinitionResponse {
1252            definitions: edit_prediction_definitions_to_proto(response),
1253        }
1254    }
1255
1256    async fn response_from_proto(
1257        self,
1258        message: proto::GetEditPredictionTypeDefinitionResponse,
1259        _: Entity<LspStore>,
1260        _: Entity<Buffer>,
1261        _: AsyncApp,
1262    ) -> Result<Vec<EditPredictionDefinition>> {
1263        edit_prediction_definitions_from_proto(message.definitions)
1264    }
1265
1266    fn buffer_id_from_proto(message: &proto::GetEditPredictionTypeDefinition) -> Result<BufferId> {
1267        BufferId::new(message.buffer_id)
1268    }
1269}
1270
1271fn language_server_for_buffer(
1272    lsp_store: &Entity<LspStore>,
1273    buffer: &Entity<Buffer>,
1274    server_id: LanguageServerId,
1275    cx: &mut AsyncApp,
1276) -> Result<(Arc<CachedLspAdapter>, Arc<LanguageServer>)> {
1277    lsp_store
1278        .update(cx, |lsp_store, cx| {
1279            buffer.update(cx, |buffer, cx| {
1280                lsp_store
1281                    .language_server_for_local_buffer(buffer, server_id, cx)
1282                    .map(|(adapter, server)| (adapter.clone(), server.clone()))
1283            })
1284        })
1285        .context("no language server found for buffer")
1286}
1287
1288pub async fn location_links_from_proto(
1289    proto_links: Vec<proto::LocationLink>,
1290    lsp_store: Entity<LspStore>,
1291    mut cx: AsyncApp,
1292) -> Result<Vec<LocationLink>> {
1293    let mut links = Vec::new();
1294
1295    for link in proto_links {
1296        links.push(location_link_from_proto(link, lsp_store.clone(), &mut cx).await?)
1297    }
1298
1299    Ok(links)
1300}
1301
1302pub fn location_link_from_proto(
1303    link: proto::LocationLink,
1304    lsp_store: Entity<LspStore>,
1305    cx: &mut AsyncApp,
1306) -> Task<Result<LocationLink>> {
1307    cx.spawn(async move |cx| {
1308        let origin = match link.origin {
1309            Some(origin) => {
1310                let buffer_id = BufferId::new(origin.buffer_id)?;
1311                let buffer = lsp_store
1312                    .update(cx, |lsp_store, cx| {
1313                        lsp_store.wait_for_remote_buffer(buffer_id, cx)
1314                    })
1315                    .await?;
1316                let start = origin
1317                    .start
1318                    .and_then(deserialize_anchor)
1319                    .context("missing origin start")?;
1320                let end = origin
1321                    .end
1322                    .and_then(deserialize_anchor)
1323                    .context("missing origin end")?;
1324                buffer
1325                    .update(cx, |buffer, _| buffer.wait_for_anchors([start, end]))
1326                    .await?;
1327                Some(Location {
1328                    buffer,
1329                    range: start..end,
1330                })
1331            }
1332            None => None,
1333        };
1334
1335        let target = link.target.context("missing target")?;
1336        let buffer_id = BufferId::new(target.buffer_id)?;
1337        let buffer = lsp_store
1338            .update(cx, |lsp_store, cx| {
1339                lsp_store.wait_for_remote_buffer(buffer_id, cx)
1340            })
1341            .await?;
1342        let start = target
1343            .start
1344            .and_then(deserialize_anchor)
1345            .context("missing target start")?;
1346        let end = target
1347            .end
1348            .and_then(deserialize_anchor)
1349            .context("missing target end")?;
1350        buffer
1351            .update(cx, |buffer, _| buffer.wait_for_anchors([start, end]))
1352            .await?;
1353        let target = Location {
1354            buffer,
1355            range: start..end,
1356        };
1357        Ok(LocationLink { origin, target })
1358    })
1359}
1360
1361pub async fn location_links_from_lsp(
1362    message: Option<lsp::GotoDefinitionResponse>,
1363    lsp_store: Entity<LspStore>,
1364    buffer: Entity<Buffer>,
1365    server_id: LanguageServerId,
1366    mut cx: AsyncApp,
1367) -> Result<Vec<LocationLink>> {
1368    let unresolved_links = definition_locations_from_lsp(message);
1369
1370    let (_, language_server) = language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
1371    let mut definitions = Vec::new();
1372    for (origin_range, target_uri, target_range) in unresolved_links {
1373        let target_buffer_handle = lsp_store
1374            .update(&mut cx, |this, cx| {
1375                this.open_local_buffer_via_lsp(target_uri, language_server.server_id(), cx)
1376            })
1377            .await?;
1378
1379        cx.update(|cx| {
1380            let origin_location = origin_range.map(|origin_range| {
1381                let origin_buffer = buffer.read(cx);
1382                let origin_start =
1383                    origin_buffer.clip_point_utf16(point_from_lsp(origin_range.start), Bias::Left);
1384                let origin_end =
1385                    origin_buffer.clip_point_utf16(point_from_lsp(origin_range.end), Bias::Left);
1386                Location {
1387                    buffer: buffer.clone(),
1388                    range: origin_buffer.anchor_after(origin_start)
1389                        ..origin_buffer.anchor_before(origin_end),
1390                }
1391            });
1392
1393            let target_buffer = target_buffer_handle.read(cx);
1394            let target_start =
1395                target_buffer.clip_point_utf16(point_from_lsp(target_range.start), Bias::Left);
1396            let target_end =
1397                target_buffer.clip_point_utf16(point_from_lsp(target_range.end), Bias::Left);
1398            let target_location = Location {
1399                buffer: target_buffer_handle,
1400                range: target_buffer.anchor_after(target_start)
1401                    ..target_buffer.anchor_before(target_end),
1402            };
1403
1404            definitions.push(LocationLink {
1405                origin: origin_location,
1406                target: target_location,
1407            })
1408        });
1409    }
1410    Ok(definitions)
1411}
1412
1413fn definition_locations_from_lsp(
1414    message: Option<lsp::GotoDefinitionResponse>,
1415) -> Vec<(Option<lsp::Range>, lsp::Uri, lsp::Range)> {
1416    let Some(message) = message else {
1417        return Vec::new();
1418    };
1419
1420    let mut locations = Vec::new();
1421    match message {
1422        lsp::GotoDefinitionResponse::Scalar(location) => {
1423            locations.push((None, location.uri, location.range));
1424        }
1425
1426        lsp::GotoDefinitionResponse::Array(locations_from_lsp) => {
1427            locations.extend(
1428                locations_from_lsp
1429                    .into_iter()
1430                    .map(|location| (None, location.uri, location.range)),
1431            );
1432        }
1433
1434        lsp::GotoDefinitionResponse::Link(links) => {
1435            locations.extend(links.into_iter().map(|link| {
1436                (
1437                    link.origin_selection_range,
1438                    link.target_uri,
1439                    link.target_selection_range,
1440                )
1441            }));
1442        }
1443    }
1444    locations
1445}
1446
1447fn edit_prediction_definitions_from_lsp(
1448    message: Option<lsp::GotoDefinitionResponse>,
1449    lsp_store: Entity<LspStore>,
1450    mut cx: AsyncApp,
1451) -> Result<Vec<EditPredictionDefinition>> {
1452    let unresolved_locations = definition_locations_from_lsp(message);
1453    lsp_store.update(&mut cx, |lsp_store, cx| {
1454        use util::paths::UrlExt as _;
1455        let mut definitions = Vec::new();
1456        let worktree_store = lsp_store.worktree_store().read(cx);
1457        let path_style = worktree_store.path_style();
1458
1459        for (_, uri, range) in unresolved_locations {
1460            let Ok(abs_path) = uri.to_file_path_ext(path_style) else {
1461                continue;
1462            };
1463            let Some((worktree, relative_path)) = worktree_store.find_worktree(&abs_path, cx)
1464            else {
1465                continue;
1466            };
1467            let worktree = worktree.read(cx);
1468            if !worktree.is_visible() || worktree.is_single_file() {
1469                continue;
1470            }
1471            definitions.push(EditPredictionDefinition {
1472                path: ProjectPath {
1473                    worktree_id: worktree.id(),
1474                    path: relative_path,
1475                },
1476                range: point_from_lsp(range.start)..point_from_lsp(range.end),
1477            });
1478        }
1479
1480        Ok(definitions)
1481    })
1482}
1483
1484async fn edit_prediction_position_from_proto(
1485    position: Option<proto::Anchor>,
1486    version: Vec<proto::VectorClockEntry>,
1487    buffer: Entity<Buffer>,
1488    cx: &mut AsyncApp,
1489) -> Result<PointUtf16> {
1490    let position = position
1491        .and_then(deserialize_anchor)
1492        .context("invalid position")?;
1493    buffer
1494        .update(cx, |buffer, _| {
1495            buffer.wait_for_version(deserialize_version(&version))
1496        })
1497        .await?;
1498    Ok(buffer.read_with(cx, |buffer, _| position.to_point_utf16(buffer)))
1499}
1500
1501pub async fn location_link_from_lsp(
1502    link: lsp::LocationLink,
1503    lsp_store: &Entity<LspStore>,
1504    buffer: &Entity<Buffer>,
1505    server_id: LanguageServerId,
1506    cx: &mut AsyncApp,
1507) -> Result<LocationLink> {
1508    let (_, language_server) = language_server_for_buffer(lsp_store, buffer, server_id, cx)?;
1509
1510    let (origin_range, target_uri, target_range) = (
1511        link.origin_selection_range,
1512        link.target_uri,
1513        link.target_selection_range,
1514    );
1515
1516    let target_buffer_handle = lsp_store
1517        .update(cx, |lsp_store, cx| {
1518            lsp_store.open_local_buffer_via_lsp(target_uri, language_server.server_id(), cx)
1519        })
1520        .await?;
1521
1522    Ok(cx.update(|cx| {
1523        let origin_location = origin_range.map(|origin_range| {
1524            let origin_buffer = buffer.read(cx);
1525            let origin_start =
1526                origin_buffer.clip_point_utf16(point_from_lsp(origin_range.start), Bias::Left);
1527            let origin_end =
1528                origin_buffer.clip_point_utf16(point_from_lsp(origin_range.end), Bias::Left);
1529            Location {
1530                buffer: buffer.clone(),
1531                range: origin_buffer.anchor_after(origin_start)
1532                    ..origin_buffer.anchor_before(origin_end),
1533            }
1534        });
1535
1536        let target_buffer = target_buffer_handle.read(cx);
1537        let target_start =
1538            target_buffer.clip_point_utf16(point_from_lsp(target_range.start), Bias::Left);
1539        let target_end =
1540            target_buffer.clip_point_utf16(point_from_lsp(target_range.end), Bias::Left);
1541        let target_location = Location {
1542            buffer: target_buffer_handle,
1543            range: target_buffer.anchor_after(target_start)
1544                ..target_buffer.anchor_before(target_end),
1545        };
1546
1547        LocationLink {
1548            origin: origin_location,
1549            target: target_location,
1550        }
1551    }))
1552}
1553
1554pub fn location_links_to_proto(
1555    links: Vec<LocationLink>,
1556    lsp_store: &mut LspStore,
1557    peer_id: PeerId,
1558    cx: &mut App,
1559) -> Vec<proto::LocationLink> {
1560    links
1561        .into_iter()
1562        .map(|definition| location_link_to_proto(definition, lsp_store, peer_id, cx))
1563        .collect()
1564}
1565
1566pub fn location_link_to_proto(
1567    location: LocationLink,
1568    lsp_store: &mut LspStore,
1569    peer_id: PeerId,
1570    cx: &mut App,
1571) -> proto::LocationLink {
1572    let origin = location.origin.map(|origin| {
1573        lsp_store
1574            .buffer_store()
1575            .update(cx, |buffer_store, cx| {
1576                buffer_store.create_buffer_for_peer(&origin.buffer, peer_id, cx)
1577            })
1578            .detach_and_log_err(cx);
1579
1580        let buffer_id = origin.buffer.read(cx).remote_id().into();
1581        proto::Location {
1582            start: Some(serialize_anchor(&origin.range.start)),
1583            end: Some(serialize_anchor(&origin.range.end)),
1584            buffer_id,
1585        }
1586    });
1587
1588    lsp_store
1589        .buffer_store()
1590        .update(cx, |buffer_store, cx| {
1591            buffer_store.create_buffer_for_peer(&location.target.buffer, peer_id, cx)
1592        })
1593        .detach_and_log_err(cx);
1594
1595    let buffer_id = location.target.buffer.read(cx).remote_id().into();
1596    let target = proto::Location {
1597        start: Some(serialize_anchor(&location.target.range.start)),
1598        end: Some(serialize_anchor(&location.target.range.end)),
1599        buffer_id,
1600    };
1601
1602    proto::LocationLink {
1603        origin,
1604        target: Some(target),
1605    }
1606}
1607
1608fn edit_prediction_definitions_to_proto(
1609    definitions: Vec<EditPredictionDefinition>,
1610) -> Vec<proto::EditPredictionDefinition> {
1611    definitions
1612        .into_iter()
1613        .map(|definition| proto::EditPredictionDefinition {
1614            worktree_id: definition.path.worktree_id.to_proto(),
1615            path: definition.path.path.as_ref().as_unix_str().to_owned(),
1616            start: Some(proto::PointUtf16 {
1617                row: definition.range.start.0.row,
1618                column: definition.range.start.0.column,
1619            }),
1620            end: Some(proto::PointUtf16 {
1621                row: definition.range.end.0.row,
1622                column: definition.range.end.0.column,
1623            }),
1624        })
1625        .collect()
1626}
1627
1628fn edit_prediction_definitions_from_proto(
1629    definitions: Vec<proto::EditPredictionDefinition>,
1630) -> Result<Vec<EditPredictionDefinition>> {
1631    definitions
1632        .into_iter()
1633        .map(|definition| {
1634            let start = definition.start.context("missing definition start")?;
1635            let end = definition.end.context("missing definition end")?;
1636            Ok(EditPredictionDefinition {
1637                path: ProjectPath {
1638                    worktree_id: worktree::WorktreeId::from_proto(definition.worktree_id),
1639                    path: RelPath::from_unix_str(&definition.path)
1640                        .context("invalid path")?
1641                        .into(),
1642                },
1643                range: Unclipped(PointUtf16::new(start.row, start.column))
1644                    ..Unclipped(PointUtf16::new(end.row, end.column)),
1645            })
1646        })
1647        .collect()
1648}
1649
1650#[async_trait(?Send)]
1651impl LspCommand for GetReferences {
1652    type Response = Vec<Location>;
1653    type LspRequest = lsp::request::References;
1654    type ProtoRequest = proto::GetReferences;
1655
1656    fn display_name(&self) -> &str {
1657        "Find all references"
1658    }
1659
1660    fn status(&self) -> Option<String> {
1661        Some("Finding references...".to_owned())
1662    }
1663
1664    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1665        match &capabilities.server_capabilities.references_provider {
1666            Some(OneOf::Left(has_support)) => *has_support,
1667            Some(OneOf::Right(_)) => true,
1668            None => false,
1669        }
1670    }
1671
1672    fn to_lsp(
1673        &self,
1674        path: &Path,
1675        _: &Buffer,
1676        _: &Arc<LanguageServer>,
1677        _: &App,
1678    ) -> Result<lsp::ReferenceParams> {
1679        Ok(lsp::ReferenceParams {
1680            text_document_position: make_lsp_text_document_position(path, self.position)?,
1681            work_done_progress_params: Default::default(),
1682            partial_result_params: Default::default(),
1683            context: lsp::ReferenceContext {
1684                include_declaration: true,
1685            },
1686        })
1687    }
1688
1689    async fn response_from_lsp(
1690        self,
1691        locations: Option<Vec<lsp::Location>>,
1692        lsp_store: Entity<LspStore>,
1693        buffer: Entity<Buffer>,
1694        server_id: LanguageServerId,
1695        mut cx: AsyncApp,
1696    ) -> Result<Vec<Location>> {
1697        let mut references = Vec::new();
1698        let (_, language_server) =
1699            language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
1700
1701        if let Some(locations) = locations {
1702            for lsp_location in locations {
1703                let target_buffer_handle = lsp_store
1704                    .update(&mut cx, |lsp_store, cx| {
1705                        lsp_store.open_local_buffer_via_lsp(
1706                            lsp_location.uri,
1707                            language_server.server_id(),
1708                            cx,
1709                        )
1710                    })
1711                    .await?;
1712
1713                target_buffer_handle
1714                    .clone()
1715                    .read_with(&cx, |target_buffer, _| {
1716                        let target_start = target_buffer
1717                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
1718                        let target_end = target_buffer
1719                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
1720                        references.push(Location {
1721                            buffer: target_buffer_handle,
1722                            range: target_buffer.anchor_after(target_start)
1723                                ..target_buffer.anchor_before(target_end),
1724                        });
1725                    });
1726            }
1727        }
1728
1729        Ok(references)
1730    }
1731
1732    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetReferences {
1733        proto::GetReferences {
1734            project_id,
1735            buffer_id: buffer.remote_id().into(),
1736            position: Some(language::proto::serialize_anchor(
1737                &buffer.anchor_before(self.position),
1738            )),
1739            version: serialize_version(&buffer.version()),
1740        }
1741    }
1742
1743    async fn from_proto(
1744        message: proto::GetReferences,
1745        _: Entity<LspStore>,
1746        buffer: Entity<Buffer>,
1747        mut cx: AsyncApp,
1748    ) -> Result<Self> {
1749        let position = message
1750            .position
1751            .and_then(deserialize_anchor)
1752            .context("invalid position")?;
1753        buffer
1754            .update(&mut cx, |buffer, _| {
1755                buffer.wait_for_version(deserialize_version(&message.version))
1756            })
1757            .await?;
1758        Ok(Self {
1759            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
1760        })
1761    }
1762
1763    fn response_to_proto(
1764        response: Vec<Location>,
1765        lsp_store: &mut LspStore,
1766        peer_id: PeerId,
1767        _: &clock::Global,
1768        cx: &mut App,
1769    ) -> proto::GetReferencesResponse {
1770        let locations = response
1771            .into_iter()
1772            .map(|definition| {
1773                lsp_store
1774                    .buffer_store()
1775                    .update(cx, |buffer_store, cx| {
1776                        buffer_store.create_buffer_for_peer(&definition.buffer, peer_id, cx)
1777                    })
1778                    .detach_and_log_err(cx);
1779                let buffer_id = definition.buffer.read(cx).remote_id();
1780                proto::Location {
1781                    start: Some(serialize_anchor(&definition.range.start)),
1782                    end: Some(serialize_anchor(&definition.range.end)),
1783                    buffer_id: buffer_id.into(),
1784                }
1785            })
1786            .collect();
1787        proto::GetReferencesResponse { locations }
1788    }
1789
1790    async fn response_from_proto(
1791        self,
1792        message: proto::GetReferencesResponse,
1793        project: Entity<LspStore>,
1794        _: Entity<Buffer>,
1795        mut cx: AsyncApp,
1796    ) -> Result<Vec<Location>> {
1797        let mut locations = Vec::new();
1798        for location in message.locations {
1799            let buffer_id = BufferId::new(location.buffer_id)?;
1800            let target_buffer = project
1801                .update(&mut cx, |this, cx| {
1802                    this.wait_for_remote_buffer(buffer_id, cx)
1803                })
1804                .await?;
1805            let start = location
1806                .start
1807                .and_then(deserialize_anchor)
1808                .context("missing target start")?;
1809            let end = location
1810                .end
1811                .and_then(deserialize_anchor)
1812                .context("missing target end")?;
1813            target_buffer
1814                .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))
1815                .await?;
1816            locations.push(Location {
1817                buffer: target_buffer,
1818                range: start..end,
1819            })
1820        }
1821        Ok(locations)
1822    }
1823
1824    fn buffer_id_from_proto(message: &proto::GetReferences) -> Result<BufferId> {
1825        BufferId::new(message.buffer_id)
1826    }
1827}
1828
1829#[async_trait(?Send)]
1830impl LspCommand for GetDocumentHighlights {
1831    type Response = Vec<DocumentHighlight>;
1832    type LspRequest = lsp::request::DocumentHighlightRequest;
1833    type ProtoRequest = proto::GetDocumentHighlights;
1834
1835    fn display_name(&self) -> &str {
1836        "Get document highlights"
1837    }
1838
1839    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1840        capabilities
1841            .server_capabilities
1842            .document_highlight_provider
1843            .is_some_and(|capability| match capability {
1844                OneOf::Left(supported) => supported,
1845                OneOf::Right(_options) => true,
1846            })
1847    }
1848
1849    fn to_lsp(
1850        &self,
1851        path: &Path,
1852        _: &Buffer,
1853        _: &Arc<LanguageServer>,
1854        _: &App,
1855    ) -> Result<lsp::DocumentHighlightParams> {
1856        Ok(lsp::DocumentHighlightParams {
1857            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
1858            work_done_progress_params: Default::default(),
1859            partial_result_params: Default::default(),
1860        })
1861    }
1862
1863    async fn response_from_lsp(
1864        self,
1865        lsp_highlights: Option<Vec<lsp::DocumentHighlight>>,
1866        _: Entity<LspStore>,
1867        buffer: Entity<Buffer>,
1868        _: LanguageServerId,
1869        cx: AsyncApp,
1870    ) -> Result<Vec<DocumentHighlight>> {
1871        Ok(buffer.read_with(&cx, |buffer, _| {
1872            let mut lsp_highlights = lsp_highlights.unwrap_or_default();
1873            lsp_highlights.sort_unstable_by_key(|h| (h.range.start, Reverse(h.range.end)));
1874            lsp_highlights
1875                .into_iter()
1876                .map(|lsp_highlight| {
1877                    let start = buffer
1878                        .clip_point_utf16(point_from_lsp(lsp_highlight.range.start), Bias::Left);
1879                    let end = buffer
1880                        .clip_point_utf16(point_from_lsp(lsp_highlight.range.end), Bias::Left);
1881                    DocumentHighlight {
1882                        range: buffer.anchor_after(start)..buffer.anchor_before(end),
1883                        kind: lsp_highlight
1884                            .kind
1885                            .unwrap_or(lsp::DocumentHighlightKind::READ),
1886                    }
1887                })
1888                .collect()
1889        }))
1890    }
1891
1892    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDocumentHighlights {
1893        proto::GetDocumentHighlights {
1894            project_id,
1895            buffer_id: buffer.remote_id().into(),
1896            position: Some(language::proto::serialize_anchor(
1897                &buffer.anchor_before(self.position),
1898            )),
1899            version: serialize_version(&buffer.version()),
1900        }
1901    }
1902
1903    async fn from_proto(
1904        message: proto::GetDocumentHighlights,
1905        _: Entity<LspStore>,
1906        buffer: Entity<Buffer>,
1907        mut cx: AsyncApp,
1908    ) -> Result<Self> {
1909        let position = message
1910            .position
1911            .and_then(deserialize_anchor)
1912            .context("invalid position")?;
1913        buffer
1914            .update(&mut cx, |buffer, _| {
1915                buffer.wait_for_version(deserialize_version(&message.version))
1916            })
1917            .await?;
1918        Ok(Self {
1919            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
1920        })
1921    }
1922
1923    fn response_to_proto(
1924        response: Vec<DocumentHighlight>,
1925        _: &mut LspStore,
1926        _: PeerId,
1927        _: &clock::Global,
1928        _: &mut App,
1929    ) -> proto::GetDocumentHighlightsResponse {
1930        let highlights = response
1931            .into_iter()
1932            .map(|highlight| proto::DocumentHighlight {
1933                start: Some(serialize_anchor(&highlight.range.start)),
1934                end: Some(serialize_anchor(&highlight.range.end)),
1935                kind: match highlight.kind {
1936                    DocumentHighlightKind::TEXT => proto::document_highlight::Kind::Text.into(),
1937                    DocumentHighlightKind::WRITE => proto::document_highlight::Kind::Write.into(),
1938                    DocumentHighlightKind::READ => proto::document_highlight::Kind::Read.into(),
1939                    _ => proto::document_highlight::Kind::Text.into(),
1940                },
1941            })
1942            .collect();
1943        proto::GetDocumentHighlightsResponse { highlights }
1944    }
1945
1946    async fn response_from_proto(
1947        self,
1948        message: proto::GetDocumentHighlightsResponse,
1949        _: Entity<LspStore>,
1950        buffer: Entity<Buffer>,
1951        mut cx: AsyncApp,
1952    ) -> Result<Vec<DocumentHighlight>> {
1953        let mut highlights = Vec::new();
1954        for highlight in message.highlights {
1955            let start = highlight
1956                .start
1957                .and_then(deserialize_anchor)
1958                .context("missing target start")?;
1959            let end = highlight
1960                .end
1961                .and_then(deserialize_anchor)
1962                .context("missing target end")?;
1963            buffer
1964                .update(&mut cx, |buffer, _| buffer.wait_for_anchors([start, end]))
1965                .await?;
1966            let kind = match proto::document_highlight::Kind::from_i32(highlight.kind) {
1967                Some(proto::document_highlight::Kind::Text) => DocumentHighlightKind::TEXT,
1968                Some(proto::document_highlight::Kind::Read) => DocumentHighlightKind::READ,
1969                Some(proto::document_highlight::Kind::Write) => DocumentHighlightKind::WRITE,
1970                None => DocumentHighlightKind::TEXT,
1971            };
1972            highlights.push(DocumentHighlight {
1973                range: start..end,
1974                kind,
1975            });
1976        }
1977        Ok(highlights)
1978    }
1979
1980    fn buffer_id_from_proto(message: &proto::GetDocumentHighlights) -> Result<BufferId> {
1981        BufferId::new(message.buffer_id)
1982    }
1983}
1984
1985#[async_trait(?Send)]
1986impl LspCommand for GetDocumentSymbols {
1987    type Response = Vec<DocumentSymbol>;
1988    type LspRequest = lsp::request::DocumentSymbolRequest;
1989    type ProtoRequest = proto::GetDocumentSymbols;
1990
1991    fn display_name(&self) -> &str {
1992        "Get document symbols"
1993    }
1994
1995    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
1996        capabilities
1997            .server_capabilities
1998            .document_symbol_provider
1999            .is_some_and(|capability| match capability {
2000                OneOf::Left(supported) => supported,
2001                OneOf::Right(_options) => true,
2002            })
2003    }
2004
2005    fn to_lsp(
2006        &self,
2007        path: &Path,
2008        _: &Buffer,
2009        _: &Arc<LanguageServer>,
2010        _: &App,
2011    ) -> Result<lsp::DocumentSymbolParams> {
2012        Ok(lsp::DocumentSymbolParams {
2013            text_document: make_text_document_identifier(path)?,
2014            work_done_progress_params: Default::default(),
2015            partial_result_params: Default::default(),
2016        })
2017    }
2018
2019    async fn response_from_lsp(
2020        self,
2021        lsp_symbols: Option<lsp::DocumentSymbolResponse>,
2022        _: Entity<LspStore>,
2023        _: Entity<Buffer>,
2024        _: LanguageServerId,
2025        _: AsyncApp,
2026    ) -> Result<Vec<DocumentSymbol>> {
2027        let Some(lsp_symbols) = lsp_symbols else {
2028            return Ok(Vec::new());
2029        };
2030
2031        let symbols = match lsp_symbols {
2032            lsp::DocumentSymbolResponse::Flat(symbol_information) => symbol_information
2033                .into_iter()
2034                .map(|lsp_symbol| DocumentSymbol {
2035                    name: lsp_symbol.name,
2036                    kind: lsp_to_symbol_kind(lsp_symbol.kind),
2037                    range: range_from_lsp(lsp_symbol.location.range),
2038                    selection_range: range_from_lsp(lsp_symbol.location.range),
2039                    children: Vec::new(),
2040                })
2041                .collect(),
2042            lsp::DocumentSymbolResponse::Nested(nested_responses) => {
2043                fn convert_symbol(lsp_symbol: lsp::DocumentSymbol) -> DocumentSymbol {
2044                    DocumentSymbol {
2045                        name: lsp_symbol.name,
2046                        kind: lsp_to_symbol_kind(lsp_symbol.kind),
2047                        range: range_from_lsp(lsp_symbol.range),
2048                        selection_range: range_from_lsp(lsp_symbol.selection_range),
2049                        children: lsp_symbol
2050                            .children
2051                            .map(|children| {
2052                                children.into_iter().map(convert_symbol).collect::<Vec<_>>()
2053                            })
2054                            .unwrap_or_default(),
2055                    }
2056                }
2057                nested_responses.into_iter().map(convert_symbol).collect()
2058            }
2059        };
2060        Ok(symbols)
2061    }
2062
2063    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDocumentSymbols {
2064        proto::GetDocumentSymbols {
2065            project_id,
2066            buffer_id: buffer.remote_id().into(),
2067            version: serialize_version(&buffer.version()),
2068        }
2069    }
2070
2071    async fn from_proto(
2072        message: proto::GetDocumentSymbols,
2073        _: Entity<LspStore>,
2074        buffer: Entity<Buffer>,
2075        mut cx: AsyncApp,
2076    ) -> Result<Self> {
2077        buffer
2078            .update(&mut cx, |buffer, _| {
2079                buffer.wait_for_version(deserialize_version(&message.version))
2080            })
2081            .await?;
2082        Ok(Self)
2083    }
2084
2085    fn response_to_proto(
2086        response: Vec<DocumentSymbol>,
2087        _: &mut LspStore,
2088        _: PeerId,
2089        _: &clock::Global,
2090        _: &mut App,
2091    ) -> proto::GetDocumentSymbolsResponse {
2092        let symbols = response
2093            .into_iter()
2094            .map(|symbol| {
2095                fn convert_symbol_to_proto(symbol: DocumentSymbol) -> proto::DocumentSymbol {
2096                    proto::DocumentSymbol {
2097                        name: symbol.name.clone(),
2098                        kind: symbol.kind as i32,
2099                        start: Some(proto::PointUtf16 {
2100                            row: symbol.range.start.0.row,
2101                            column: symbol.range.start.0.column,
2102                        }),
2103                        end: Some(proto::PointUtf16 {
2104                            row: symbol.range.end.0.row,
2105                            column: symbol.range.end.0.column,
2106                        }),
2107                        selection_start: Some(proto::PointUtf16 {
2108                            row: symbol.selection_range.start.0.row,
2109                            column: symbol.selection_range.start.0.column,
2110                        }),
2111                        selection_end: Some(proto::PointUtf16 {
2112                            row: symbol.selection_range.end.0.row,
2113                            column: symbol.selection_range.end.0.column,
2114                        }),
2115                        children: symbol
2116                            .children
2117                            .into_iter()
2118                            .map(convert_symbol_to_proto)
2119                            .collect(),
2120                    }
2121                }
2122                convert_symbol_to_proto(symbol)
2123            })
2124            .collect::<Vec<_>>();
2125
2126        proto::GetDocumentSymbolsResponse { symbols }
2127    }
2128
2129    async fn response_from_proto(
2130        self,
2131        message: proto::GetDocumentSymbolsResponse,
2132        _: Entity<LspStore>,
2133        _: Entity<Buffer>,
2134        _: AsyncApp,
2135    ) -> Result<Vec<DocumentSymbol>> {
2136        let mut symbols = Vec::with_capacity(message.symbols.len());
2137        for serialized_symbol in message.symbols {
2138            fn deserialize_symbol_with_children(
2139                serialized_symbol: proto::DocumentSymbol,
2140            ) -> Result<DocumentSymbol> {
2141                let kind = language::SymbolKind::from_proto(serialized_symbol.kind);
2142
2143                let start = serialized_symbol.start.context("invalid start")?;
2144                let end = serialized_symbol.end.context("invalid end")?;
2145
2146                let selection_start = serialized_symbol
2147                    .selection_start
2148                    .context("invalid selection start")?;
2149                let selection_end = serialized_symbol
2150                    .selection_end
2151                    .context("invalid selection end")?;
2152
2153                Ok(DocumentSymbol {
2154                    name: serialized_symbol.name,
2155                    kind,
2156                    range: Unclipped(PointUtf16::new(start.row, start.column))
2157                        ..Unclipped(PointUtf16::new(end.row, end.column)),
2158                    selection_range: Unclipped(PointUtf16::new(
2159                        selection_start.row,
2160                        selection_start.column,
2161                    ))
2162                        ..Unclipped(PointUtf16::new(selection_end.row, selection_end.column)),
2163                    children: serialized_symbol
2164                        .children
2165                        .into_iter()
2166                        .filter_map(|symbol| deserialize_symbol_with_children(symbol).ok())
2167                        .collect::<Vec<_>>(),
2168                })
2169            }
2170
2171            symbols.push(deserialize_symbol_with_children(serialized_symbol)?);
2172        }
2173
2174        Ok(symbols)
2175    }
2176
2177    fn buffer_id_from_proto(message: &proto::GetDocumentSymbols) -> Result<BufferId> {
2178        BufferId::new(message.buffer_id)
2179    }
2180}
2181
2182#[async_trait(?Send)]
2183impl LspCommand for GetSignatureHelp {
2184    type Response = Option<SignatureHelp>;
2185    type LspRequest = lsp::SignatureHelpRequest;
2186    type ProtoRequest = proto::GetSignatureHelp;
2187
2188    fn display_name(&self) -> &str {
2189        "Get signature help"
2190    }
2191
2192    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
2193        capabilities
2194            .server_capabilities
2195            .signature_help_provider
2196            .is_some()
2197    }
2198
2199    fn to_lsp(
2200        &self,
2201        path: &Path,
2202        _: &Buffer,
2203        _: &Arc<LanguageServer>,
2204        _cx: &App,
2205    ) -> Result<lsp::SignatureHelpParams> {
2206        Ok(lsp::SignatureHelpParams {
2207            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
2208            context: None,
2209            work_done_progress_params: Default::default(),
2210        })
2211    }
2212
2213    async fn response_from_lsp(
2214        self,
2215        message: Option<lsp::SignatureHelp>,
2216        lsp_store: Entity<LspStore>,
2217        _: Entity<Buffer>,
2218        id: LanguageServerId,
2219        cx: AsyncApp,
2220    ) -> Result<Self::Response> {
2221        let Some(message) = message else {
2222            return Ok(None);
2223        };
2224        Ok(cx.update(|cx| {
2225            SignatureHelp::new(
2226                message,
2227                Some(lsp_store.read(cx).languages.clone()),
2228                Some(id),
2229                cx,
2230            )
2231        }))
2232    }
2233
2234    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest {
2235        let offset = buffer.point_utf16_to_offset(self.position);
2236        proto::GetSignatureHelp {
2237            project_id,
2238            buffer_id: buffer.remote_id().to_proto(),
2239            position: Some(serialize_anchor(&buffer.anchor_after(offset))),
2240            version: serialize_version(&buffer.version()),
2241        }
2242    }
2243
2244    async fn from_proto(
2245        payload: Self::ProtoRequest,
2246        _: Entity<LspStore>,
2247        buffer: Entity<Buffer>,
2248        mut cx: AsyncApp,
2249    ) -> Result<Self> {
2250        buffer
2251            .update(&mut cx, |buffer, _| {
2252                buffer.wait_for_version(deserialize_version(&payload.version))
2253            })
2254            .await
2255            .with_context(|| format!("waiting for version for buffer {}", buffer.entity_id()))?;
2256        let buffer_snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot());
2257        Ok(Self {
2258            position: payload
2259                .position
2260                .and_then(deserialize_anchor)
2261                .context("invalid position")?
2262                .to_point_utf16(&buffer_snapshot),
2263        })
2264    }
2265
2266    fn response_to_proto(
2267        response: Self::Response,
2268        _: &mut LspStore,
2269        _: PeerId,
2270        _: &Global,
2271        _: &mut App,
2272    ) -> proto::GetSignatureHelpResponse {
2273        proto::GetSignatureHelpResponse {
2274            signature_help: response
2275                .map(|signature_help| lsp_to_proto_signature(signature_help.original_data)),
2276        }
2277    }
2278
2279    async fn response_from_proto(
2280        self,
2281        response: proto::GetSignatureHelpResponse,
2282        lsp_store: Entity<LspStore>,
2283        _: Entity<Buffer>,
2284        cx: AsyncApp,
2285    ) -> Result<Self::Response> {
2286        Ok(cx.update(|cx| {
2287            response
2288                .signature_help
2289                .map(proto_to_lsp_signature)
2290                .and_then(|signature| {
2291                    SignatureHelp::new(
2292                        signature,
2293                        Some(lsp_store.read(cx).languages.clone()),
2294                        None,
2295                        cx,
2296                    )
2297                })
2298        }))
2299    }
2300
2301    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId> {
2302        BufferId::new(message.buffer_id)
2303    }
2304}
2305
2306#[async_trait(?Send)]
2307impl LspCommand for GetHover {
2308    type Response = Option<Hover>;
2309    type LspRequest = lsp::request::HoverRequest;
2310    type ProtoRequest = proto::GetHover;
2311
2312    fn display_name(&self) -> &str {
2313        "Get hover"
2314    }
2315
2316    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
2317        match capabilities.server_capabilities.hover_provider {
2318            Some(lsp::HoverProviderCapability::Simple(enabled)) => enabled,
2319            Some(lsp::HoverProviderCapability::Options(_)) => true,
2320            None => false,
2321        }
2322    }
2323
2324    fn to_lsp(
2325        &self,
2326        path: &Path,
2327        _: &Buffer,
2328        _: &Arc<LanguageServer>,
2329        _: &App,
2330    ) -> Result<lsp::HoverParams> {
2331        Ok(lsp::HoverParams {
2332            text_document_position_params: make_lsp_text_document_position(path, self.position)?,
2333            work_done_progress_params: Default::default(),
2334        })
2335    }
2336
2337    async fn response_from_lsp(
2338        self,
2339        message: Option<lsp::Hover>,
2340        _: Entity<LspStore>,
2341        buffer: Entity<Buffer>,
2342        _: LanguageServerId,
2343        cx: AsyncApp,
2344    ) -> Result<Self::Response> {
2345        let Some(hover) = message else {
2346            return Ok(None);
2347        };
2348
2349        let (language, range) = buffer.read_with(&cx, |buffer, _| {
2350            (
2351                buffer.language().cloned(),
2352                hover.range.map(|range| {
2353                    let token_start =
2354                        buffer.clip_point_utf16(point_from_lsp(range.start), Bias::Left);
2355                    let token_end = buffer.clip_point_utf16(point_from_lsp(range.end), Bias::Left);
2356                    buffer.anchor_after(token_start)..buffer.anchor_before(token_end)
2357                }),
2358            )
2359        });
2360
2361        fn hover_blocks_from_marked_string(marked_string: lsp::MarkedString) -> Option<HoverBlock> {
2362            let block = match marked_string {
2363                lsp::MarkedString::String(content) => HoverBlock {
2364                    text: content,
2365                    kind: HoverBlockKind::Markdown,
2366                },
2367                lsp::MarkedString::LanguageString(lsp::LanguageString { language, value }) => {
2368                    HoverBlock {
2369                        text: value,
2370                        kind: HoverBlockKind::Code { language },
2371                    }
2372                }
2373            };
2374            if block.text.is_empty() {
2375                None
2376            } else {
2377                Some(block)
2378            }
2379        }
2380
2381        let contents = match hover.contents {
2382            lsp::HoverContents::Scalar(marked_string) => {
2383                hover_blocks_from_marked_string(marked_string)
2384                    .into_iter()
2385                    .collect()
2386            }
2387            lsp::HoverContents::Array(marked_strings) => marked_strings
2388                .into_iter()
2389                .filter_map(hover_blocks_from_marked_string)
2390                .collect(),
2391            lsp::HoverContents::Markup(markup_content) => vec![HoverBlock {
2392                text: markup_content.value,
2393                kind: if markup_content.kind == lsp::MarkupKind::Markdown {
2394                    HoverBlockKind::Markdown
2395                } else {
2396                    HoverBlockKind::PlainText
2397                },
2398            }],
2399        };
2400
2401        Ok(Some(Hover {
2402            contents,
2403            range,
2404            language,
2405        }))
2406    }
2407
2408    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest {
2409        proto::GetHover {
2410            project_id,
2411            buffer_id: buffer.remote_id().into(),
2412            position: Some(language::proto::serialize_anchor(
2413                &buffer.anchor_before(self.position),
2414            )),
2415            version: serialize_version(&buffer.version),
2416        }
2417    }
2418
2419    async fn from_proto(
2420        message: Self::ProtoRequest,
2421        _: Entity<LspStore>,
2422        buffer: Entity<Buffer>,
2423        mut cx: AsyncApp,
2424    ) -> Result<Self> {
2425        let position = message
2426            .position
2427            .and_then(deserialize_anchor)
2428            .context("invalid position")?;
2429        buffer
2430            .update(&mut cx, |buffer, _| {
2431                buffer.wait_for_version(deserialize_version(&message.version))
2432            })
2433            .await?;
2434        Ok(Self {
2435            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
2436        })
2437    }
2438
2439    fn response_to_proto(
2440        response: Self::Response,
2441        _: &mut LspStore,
2442        _: PeerId,
2443        _: &clock::Global,
2444        _: &mut App,
2445    ) -> proto::GetHoverResponse {
2446        if let Some(response) = response {
2447            let (start, end) = if let Some(range) = response.range {
2448                (
2449                    Some(language::proto::serialize_anchor(&range.start)),
2450                    Some(language::proto::serialize_anchor(&range.end)),
2451                )
2452            } else {
2453                (None, None)
2454            };
2455
2456            let contents = response
2457                .contents
2458                .into_iter()
2459                .map(|block| proto::HoverBlock {
2460                    text: block.text,
2461                    is_markdown: block.kind == HoverBlockKind::Markdown,
2462                    language: if let HoverBlockKind::Code { language } = block.kind {
2463                        Some(language)
2464                    } else {
2465                        None
2466                    },
2467                })
2468                .collect();
2469
2470            proto::GetHoverResponse {
2471                start,
2472                end,
2473                contents,
2474            }
2475        } else {
2476            proto::GetHoverResponse {
2477                start: None,
2478                end: None,
2479                contents: Vec::new(),
2480            }
2481        }
2482    }
2483
2484    async fn response_from_proto(
2485        self,
2486        message: proto::GetHoverResponse,
2487        _: Entity<LspStore>,
2488        buffer: Entity<Buffer>,
2489        mut cx: AsyncApp,
2490    ) -> Result<Self::Response> {
2491        let contents: Vec<_> = message
2492            .contents
2493            .into_iter()
2494            .map(|block| HoverBlock {
2495                text: block.text,
2496                kind: if let Some(language) = block.language {
2497                    HoverBlockKind::Code { language }
2498                } else if block.is_markdown {
2499                    HoverBlockKind::Markdown
2500                } else {
2501                    HoverBlockKind::PlainText
2502                },
2503            })
2504            .collect();
2505        if contents.is_empty() {
2506            return Ok(None);
2507        }
2508
2509        let language = buffer.read_with(&cx, |buffer, _| buffer.language().cloned());
2510        let range = if let (Some(start), Some(end)) = (message.start, message.end) {
2511            language::proto::deserialize_anchor(start)
2512                .and_then(|start| language::proto::deserialize_anchor(end).map(|end| start..end))
2513        } else {
2514            None
2515        };
2516        if let Some(range) = range.as_ref() {
2517            buffer
2518                .update(&mut cx, |buffer, _| {
2519                    buffer.wait_for_anchors([range.start, range.end])
2520                })
2521                .await?;
2522        }
2523
2524        Ok(Some(Hover {
2525            contents,
2526            range,
2527            language,
2528        }))
2529    }
2530
2531    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId> {
2532        BufferId::new(message.buffer_id)
2533    }
2534}
2535
2536impl GetCompletions {
2537    pub fn can_resolve_completions(capabilities: &lsp::ServerCapabilities) -> bool {
2538        capabilities
2539            .completion_provider
2540            .as_ref()
2541            .and_then(|options| options.resolve_provider)
2542            .unwrap_or(false)
2543    }
2544}
2545
2546#[async_trait(?Send)]
2547impl LspCommand for GetCompletions {
2548    type Response = CoreCompletionResponse;
2549    type LspRequest = lsp::request::Completion;
2550    type ProtoRequest = proto::GetCompletions;
2551
2552    fn display_name(&self) -> &str {
2553        "Get completion"
2554    }
2555
2556    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
2557        capabilities
2558            .server_capabilities
2559            .completion_provider
2560            .is_some()
2561    }
2562
2563    fn to_lsp(
2564        &self,
2565        path: &Path,
2566        _: &Buffer,
2567        _: &Arc<LanguageServer>,
2568        _: &App,
2569    ) -> Result<lsp::CompletionParams> {
2570        Ok(lsp::CompletionParams {
2571            text_document_position: make_lsp_text_document_position(path, self.position)?,
2572            context: Some(self.context.clone()),
2573            work_done_progress_params: Default::default(),
2574            partial_result_params: Default::default(),
2575        })
2576    }
2577
2578    async fn response_from_lsp(
2579        self,
2580        completions: Option<lsp::CompletionResponse>,
2581        lsp_store: Entity<LspStore>,
2582        buffer: Entity<Buffer>,
2583        server_id: LanguageServerId,
2584        mut cx: AsyncApp,
2585    ) -> Result<Self::Response> {
2586        let mut response_list = None;
2587        let (mut completions, mut is_incomplete) = if let Some(completions) = completions {
2588            match completions {
2589                lsp::CompletionResponse::Array(completions) => (completions, false),
2590                lsp::CompletionResponse::List(mut list) => {
2591                    let is_incomplete = list.is_incomplete;
2592                    let items = std::mem::take(&mut list.items);
2593                    response_list = Some(list);
2594                    (items, is_incomplete)
2595                }
2596            }
2597        } else {
2598            (Vec::new(), false)
2599        };
2600
2601        let unfiltered_completions_count = completions.len();
2602
2603        let language_server_adapter = lsp_store
2604            .read_with(&cx, |lsp_store, _| {
2605                lsp_store.language_server_adapter_for_id(server_id)
2606            })
2607            .with_context(|| format!("no language server with id {server_id}"))?;
2608
2609        let lsp_defaults = response_list
2610            .as_ref()
2611            .and_then(|list| list.item_defaults.clone())
2612            .map(Arc::new);
2613
2614        let mut completion_edits = Vec::new();
2615        buffer.update(&mut cx, |buffer, _cx| {
2616            let snapshot = buffer.snapshot();
2617            let clipped_position = buffer.clip_point_utf16(Unclipped(self.position), Bias::Left);
2618
2619            let mut range_for_token = None;
2620            completions.retain(|lsp_completion| {
2621                let lsp_edit = lsp_completion.text_edit.clone().or_else(|| {
2622                    let default_text_edit = lsp_defaults.as_deref()?.edit_range.as_ref()?;
2623                    let new_text = lsp_completion
2624                        .text_edit_text
2625                        .as_ref()
2626                        .unwrap_or(&lsp_completion.label)
2627                        .clone();
2628                    match default_text_edit {
2629                        CompletionListItemDefaultsEditRange::Range(range) => {
2630                            Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
2631                                range: *range,
2632                                new_text,
2633                            }))
2634                        }
2635                        CompletionListItemDefaultsEditRange::InsertAndReplace {
2636                            insert,
2637                            replace,
2638                        } => Some(lsp::CompletionTextEdit::InsertAndReplace(
2639                            lsp::InsertReplaceEdit {
2640                                new_text,
2641                                insert: *insert,
2642                                replace: *replace,
2643                            },
2644                        )),
2645                    }
2646                });
2647
2648                let edit = match lsp_edit {
2649                    // If the language server provides a range to overwrite, then
2650                    // check that the range is valid.
2651                    Some(completion_text_edit) => {
2652                        match parse_completion_text_edit(&completion_text_edit, &snapshot) {
2653                            Some(edit) => edit,
2654                            None => return false,
2655                        }
2656                    }
2657                    // If the language server does not provide a range, then infer
2658                    // the range based on the syntax tree.
2659                    None => {
2660                        if self.position != clipped_position {
2661                            log::info!("completion out of expected range ");
2662                            return false;
2663                        }
2664
2665                        let default_edit_range = lsp_defaults.as_ref().and_then(|lsp_defaults| {
2666                            lsp_defaults
2667                                .edit_range
2668                                .as_ref()
2669                                .and_then(|range| match range {
2670                                    CompletionListItemDefaultsEditRange::Range(r) => Some(r),
2671                                    _ => None,
2672                                })
2673                        });
2674
2675                        let range = if let Some(range) = default_edit_range {
2676                            let range = range_from_lsp(*range);
2677                            let start = snapshot.clip_point_utf16(range.start, Bias::Left);
2678                            let end = snapshot.clip_point_utf16(range.end, Bias::Left);
2679                            if start != range.start.0 || end != range.end.0 {
2680                                log::info!("completion out of expected range");
2681                                return false;
2682                            }
2683
2684                            snapshot.anchor_before(start)..snapshot.anchor_after(end)
2685                        } else {
2686                            range_for_token
2687                                .get_or_insert_with(|| {
2688                                    let offset = self.position.to_offset(&snapshot);
2689                                    let (range, kind) = snapshot.surrounding_word(
2690                                        offset,
2691                                        Some(CharScopeContext::Completion),
2692                                    );
2693                                    let range = if kind == Some(CharKind::Word) {
2694                                        range
2695                                    } else {
2696                                        offset..offset
2697                                    };
2698
2699                                    snapshot.anchor_before(range.start)
2700                                        ..snapshot.anchor_after(range.end)
2701                                })
2702                                .clone()
2703                        };
2704
2705                        // We already know text_edit is None here
2706                        let text = lsp_completion
2707                            .insert_text
2708                            .as_ref()
2709                            .unwrap_or(&lsp_completion.label)
2710                            .clone();
2711
2712                        ParsedCompletionEdit {
2713                            replace_range: range,
2714                            insert_range: None,
2715                            new_text: text,
2716                        }
2717                    }
2718                };
2719
2720                completion_edits.push(edit);
2721                true
2722            });
2723        });
2724
2725        // If completions were filtered out due to errors that may be transient, mark the result
2726        // incomplete so that it is re-queried.
2727        if unfiltered_completions_count != completions.len() {
2728            is_incomplete = true;
2729        }
2730
2731        language_server_adapter
2732            .process_completions(&mut completions)
2733            .await;
2734
2735        let completions = completions
2736            .into_iter()
2737            .zip(completion_edits)
2738            .map(|(mut lsp_completion, mut edit)| {
2739                LineEnding::normalize(&mut edit.new_text);
2740                if lsp_completion.data.is_none()
2741                    && let Some(default_data) = lsp_defaults
2742                        .as_ref()
2743                        .and_then(|item_defaults| item_defaults.data.clone())
2744                {
2745                    // Servers (e.g. JDTLS) prefer unchanged completions, when resolving the items later,
2746                    // so we do not insert the defaults here, but `data` is needed for resolving, so this is an exception.
2747                    lsp_completion.data = Some(default_data);
2748                }
2749                CoreCompletion {
2750                    replace_range: edit.replace_range,
2751                    new_text: edit.new_text,
2752                    source: CompletionSource::Lsp {
2753                        insert_range: edit.insert_range,
2754                        server_id,
2755                        lsp_completion: Box::new(lsp_completion),
2756                        lsp_defaults: lsp_defaults.clone(),
2757                        resolved: false,
2758                    },
2759                }
2760            })
2761            .collect();
2762
2763        Ok(CoreCompletionResponse {
2764            completions,
2765            is_incomplete,
2766        })
2767    }
2768
2769    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCompletions {
2770        let anchor = buffer.anchor_after(self.position);
2771        proto::GetCompletions {
2772            project_id,
2773            buffer_id: buffer.remote_id().into(),
2774            position: Some(language::proto::serialize_anchor(&anchor)),
2775            version: serialize_version(&buffer.version()),
2776            server_id: self.server_id.map(|id| id.to_proto()),
2777        }
2778    }
2779
2780    async fn from_proto(
2781        message: proto::GetCompletions,
2782        _: Entity<LspStore>,
2783        buffer: Entity<Buffer>,
2784        mut cx: AsyncApp,
2785    ) -> Result<Self> {
2786        let version = deserialize_version(&message.version);
2787        buffer
2788            .update(&mut cx, |buffer, _| buffer.wait_for_version(version))
2789            .await?;
2790        let position = message
2791            .position
2792            .and_then(language::proto::deserialize_anchor)
2793            .map(|p| {
2794                buffer.read_with(&cx, |buffer, _| {
2795                    buffer.clip_point_utf16(Unclipped(p.to_point_utf16(buffer)), Bias::Left)
2796                })
2797            })
2798            .context("invalid position")?;
2799        Ok(Self {
2800            position,
2801            context: CompletionContext {
2802                trigger_kind: CompletionTriggerKind::INVOKED,
2803                trigger_character: None,
2804            },
2805            server_id: message
2806                .server_id
2807                .map(|id| lsp::LanguageServerId::from_proto(id)),
2808        })
2809    }
2810
2811    fn response_to_proto(
2812        response: CoreCompletionResponse,
2813        _: &mut LspStore,
2814        _: PeerId,
2815        buffer_version: &clock::Global,
2816        _: &mut App,
2817    ) -> proto::GetCompletionsResponse {
2818        proto::GetCompletionsResponse {
2819            completions: response
2820                .completions
2821                .iter()
2822                .map(LspStore::serialize_completion)
2823                .collect(),
2824            version: serialize_version(buffer_version),
2825            can_reuse: !response.is_incomplete,
2826        }
2827    }
2828
2829    async fn response_from_proto(
2830        self,
2831        message: proto::GetCompletionsResponse,
2832        _project: Entity<LspStore>,
2833        buffer: Entity<Buffer>,
2834        mut cx: AsyncApp,
2835    ) -> Result<Self::Response> {
2836        buffer
2837            .update(&mut cx, |buffer, _| {
2838                buffer.wait_for_version(deserialize_version(&message.version))
2839            })
2840            .await?;
2841
2842        let completions = message
2843            .completions
2844            .into_iter()
2845            .map(LspStore::deserialize_completion)
2846            .collect::<Result<Vec<_>>>()?;
2847
2848        Ok(CoreCompletionResponse {
2849            completions,
2850            is_incomplete: !message.can_reuse,
2851        })
2852    }
2853
2854    fn buffer_id_from_proto(message: &proto::GetCompletions) -> Result<BufferId> {
2855        BufferId::new(message.buffer_id)
2856    }
2857}
2858
2859pub struct ParsedCompletionEdit {
2860    pub replace_range: Range<Anchor>,
2861    pub insert_range: Option<Range<Anchor>>,
2862    pub new_text: String,
2863}
2864
2865pub(crate) fn parse_completion_text_edit(
2866    edit: &lsp::CompletionTextEdit,
2867    snapshot: &BufferSnapshot,
2868) -> Option<ParsedCompletionEdit> {
2869    let (replace_range, insert_range, new_text) = match edit {
2870        lsp::CompletionTextEdit::Edit(edit) => (edit.range, None, &edit.new_text),
2871        lsp::CompletionTextEdit::InsertAndReplace(edit) => {
2872            (edit.replace, Some(edit.insert), &edit.new_text)
2873        }
2874    };
2875
2876    let replace_range = {
2877        let range = range_from_lsp(replace_range);
2878        let start = snapshot.clip_point_utf16(range.start, Bias::Left);
2879        let end = snapshot.clip_point_utf16(range.end, Bias::Left);
2880        if start != range.start.0 || end != range.end.0 {
2881            log::info!(
2882                "completion out of expected range, start: {start:?}, end: {end:?}, range: {range:?}"
2883            );
2884            return None;
2885        }
2886        snapshot.anchor_before(start)..snapshot.anchor_after(end)
2887    };
2888
2889    let insert_range = match insert_range {
2890        None => None,
2891        Some(insert_range) => {
2892            let range = range_from_lsp(insert_range);
2893            let start = snapshot.clip_point_utf16(range.start, Bias::Left);
2894            let end = snapshot.clip_point_utf16(range.end, Bias::Left);
2895            if start != range.start.0 || end != range.end.0 {
2896                log::info!("completion (insert) out of expected range");
2897                return None;
2898            }
2899            Some(snapshot.anchor_before(start)..snapshot.anchor_after(end))
2900        }
2901    };
2902
2903    Some(ParsedCompletionEdit {
2904        insert_range,
2905        replace_range,
2906        new_text: new_text.clone(),
2907    })
2908}
2909
2910#[async_trait(?Send)]
2911impl LspCommand for GetCodeActions {
2912    type Response = Vec<CodeAction>;
2913    type LspRequest = lsp::request::CodeActionRequest;
2914    type ProtoRequest = proto::GetCodeActions;
2915
2916    fn display_name(&self) -> &str {
2917        "Get code actions"
2918    }
2919
2920    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
2921        match &capabilities.server_capabilities.code_action_provider {
2922            None => false,
2923            Some(lsp::CodeActionProviderCapability::Simple(false)) => false,
2924            _ => {
2925                // If we do know that we want specific code actions AND we know that
2926                // the server only supports specific code actions, then we want to filter
2927                // down to the ones that are supported.
2928                if let Some((requested, supported)) = self
2929                    .kinds
2930                    .as_ref()
2931                    .zip(Self::supported_code_action_kinds(capabilities))
2932                {
2933                    requested.iter().any(|requested_kind| {
2934                        supported.iter().any(|supported_kind| {
2935                            code_action_kind_matches(requested_kind, supported_kind)
2936                        })
2937                    })
2938                } else {
2939                    true
2940                }
2941            }
2942        }
2943    }
2944
2945    fn to_lsp(
2946        &self,
2947        path: &Path,
2948        buffer: &Buffer,
2949        language_server: &Arc<LanguageServer>,
2950        _: &App,
2951    ) -> Result<lsp::CodeActionParams> {
2952        let mut relevant_diagnostics = Vec::new();
2953        for entry in buffer
2954            .snapshot()
2955            .diagnostics_in_range::<_, language::PointUtf16>(self.range.clone(), false)
2956        {
2957            relevant_diagnostics.push(entry.to_lsp_diagnostic_stub()?);
2958        }
2959
2960        let only = if let Some(requested) = &self.kinds {
2961            if let Some(supported_kinds) =
2962                Self::supported_code_action_kinds(language_server.adapter_server_capabilities())
2963            {
2964                let filtered = requested
2965                    .iter()
2966                    .filter(|requested_kind| {
2967                        supported_kinds.iter().any(|supported_kind| {
2968                            code_action_kind_matches(requested_kind, supported_kind)
2969                        })
2970                    })
2971                    .cloned()
2972                    .collect();
2973                Some(filtered)
2974            } else {
2975                Some(requested.clone())
2976            }
2977        } else {
2978            None
2979        };
2980
2981        Ok(lsp::CodeActionParams {
2982            text_document: make_text_document_identifier(path)?,
2983            range: range_to_lsp(self.range.to_point_utf16(buffer))?,
2984            work_done_progress_params: Default::default(),
2985            partial_result_params: Default::default(),
2986            context: lsp::CodeActionContext {
2987                diagnostics: relevant_diagnostics,
2988                only,
2989                ..lsp::CodeActionContext::default()
2990            },
2991        })
2992    }
2993
2994    async fn response_from_lsp(
2995        self,
2996        actions: Option<lsp::CodeActionResponse>,
2997        lsp_store: Entity<LspStore>,
2998        _: Entity<Buffer>,
2999        server_id: LanguageServerId,
3000        cx: AsyncApp,
3001    ) -> Result<Vec<CodeAction>> {
3002        let requested_kinds = self.kinds.as_ref();
3003
3004        let language_server = cx.update(|cx| {
3005            lsp_store
3006                .read(cx)
3007                .language_server_for_id(server_id)
3008                .with_context(|| {
3009                    format!("Missing the language server that just returned a response {server_id}")
3010                })
3011        })?;
3012
3013        let server_capabilities = language_server.capabilities();
3014        let available_commands = server_capabilities
3015            .execute_command_provider
3016            .as_ref()
3017            .map(|options| options.commands.as_slice())
3018            .unwrap_or_default();
3019        Ok(actions
3020            .unwrap_or_default()
3021            .into_iter()
3022            .filter_map(|entry| {
3023                let (lsp_action, resolved) = match entry {
3024                    lsp::CodeActionOrCommand::CodeAction(lsp_action) => {
3025                        if let Some(command) = lsp_action.command.as_ref()
3026                            && !available_commands.contains(&command.command)
3027                        {
3028                            return None;
3029                        }
3030                        (LspAction::Action(Box::new(lsp_action)), false)
3031                    }
3032                    lsp::CodeActionOrCommand::Command(command) => {
3033                        if available_commands.contains(&command.command) {
3034                            (LspAction::Command(command), true)
3035                        } else {
3036                            return None;
3037                        }
3038                    }
3039                };
3040
3041                if let Some((kinds, kind)) = requested_kinds.zip(lsp_action.action_kind())
3042                    && !kinds
3043                        .iter()
3044                        .any(|requested_kind| code_action_kind_matches(requested_kind, &kind))
3045                {
3046                    return None;
3047                }
3048
3049                Some(CodeAction {
3050                    server_id,
3051                    range: self.range.clone(),
3052                    lsp_action,
3053                    resolved,
3054                })
3055            })
3056            .collect())
3057    }
3058
3059    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCodeActions {
3060        proto::GetCodeActions {
3061            project_id,
3062            buffer_id: buffer.remote_id().into(),
3063            start: Some(language::proto::serialize_anchor(&self.range.start)),
3064            end: Some(language::proto::serialize_anchor(&self.range.end)),
3065            version: serialize_version(&buffer.version()),
3066        }
3067    }
3068
3069    async fn from_proto(
3070        message: proto::GetCodeActions,
3071        _: Entity<LspStore>,
3072        buffer: Entity<Buffer>,
3073        mut cx: AsyncApp,
3074    ) -> Result<Self> {
3075        let start = message
3076            .start
3077            .and_then(language::proto::deserialize_anchor)
3078            .context("invalid start")?;
3079        let end = message
3080            .end
3081            .and_then(language::proto::deserialize_anchor)
3082            .context("invalid end")?;
3083        buffer
3084            .update(&mut cx, |buffer, _| {
3085                buffer.wait_for_version(deserialize_version(&message.version))
3086            })
3087            .await?;
3088
3089        Ok(Self {
3090            range: start..end,
3091            kinds: None,
3092        })
3093    }
3094
3095    fn response_to_proto(
3096        code_actions: Vec<CodeAction>,
3097        _: &mut LspStore,
3098        _: PeerId,
3099        buffer_version: &clock::Global,
3100        _: &mut App,
3101    ) -> proto::GetCodeActionsResponse {
3102        proto::GetCodeActionsResponse {
3103            actions: code_actions
3104                .iter()
3105                .map(LspStore::serialize_code_action)
3106                .collect(),
3107            version: serialize_version(buffer_version),
3108        }
3109    }
3110
3111    async fn response_from_proto(
3112        self,
3113        message: proto::GetCodeActionsResponse,
3114        _: Entity<LspStore>,
3115        buffer: Entity<Buffer>,
3116        mut cx: AsyncApp,
3117    ) -> Result<Vec<CodeAction>> {
3118        buffer
3119            .update(&mut cx, |buffer, _| {
3120                buffer.wait_for_version(deserialize_version(&message.version))
3121            })
3122            .await?;
3123        message
3124            .actions
3125            .into_iter()
3126            .map(LspStore::deserialize_code_action)
3127            .collect()
3128    }
3129
3130    fn buffer_id_from_proto(message: &proto::GetCodeActions) -> Result<BufferId> {
3131        BufferId::new(message.buffer_id)
3132    }
3133}
3134
3135impl GetCodeActions {
3136    fn supported_code_action_kinds(
3137        capabilities: AdapterServerCapabilities,
3138    ) -> Option<Vec<CodeActionKind>> {
3139        match capabilities.server_capabilities.code_action_provider {
3140            Some(lsp::CodeActionProviderCapability::Options(CodeActionOptions {
3141                code_action_kinds: Some(supported_action_kinds),
3142                ..
3143            })) => Some(supported_action_kinds),
3144            _ => capabilities.code_action_kinds,
3145        }
3146    }
3147
3148    pub fn can_resolve_actions(capabilities: &ServerCapabilities) -> bool {
3149        capabilities
3150            .code_action_provider
3151            .as_ref()
3152            .and_then(|options| match options {
3153                lsp::CodeActionProviderCapability::Simple(_is_supported) => None,
3154                lsp::CodeActionProviderCapability::Options(options) => options.resolve_provider,
3155            })
3156            .unwrap_or(false)
3157    }
3158}
3159
3160impl OnTypeFormatting {
3161    pub fn supports_on_type_formatting(trigger: &str, capabilities: &ServerCapabilities) -> bool {
3162        let Some(on_type_formatting_options) = &capabilities.document_on_type_formatting_provider
3163        else {
3164            return false;
3165        };
3166        on_type_formatting_options
3167            .first_trigger_character
3168            .contains(trigger)
3169            || on_type_formatting_options
3170                .more_trigger_character
3171                .iter()
3172                .flatten()
3173                .any(|chars| chars.contains(trigger))
3174    }
3175}
3176
3177#[async_trait(?Send)]
3178impl LspCommand for OnTypeFormatting {
3179    type Response = Option<Transaction>;
3180    type LspRequest = lsp::request::OnTypeFormatting;
3181    type ProtoRequest = proto::OnTypeFormatting;
3182
3183    fn display_name(&self) -> &str {
3184        "Formatting on typing"
3185    }
3186
3187    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
3188        Self::supports_on_type_formatting(&self.trigger, &capabilities.server_capabilities)
3189    }
3190
3191    fn to_lsp(
3192        &self,
3193        path: &Path,
3194        _: &Buffer,
3195        _: &Arc<LanguageServer>,
3196        _: &App,
3197    ) -> Result<lsp::DocumentOnTypeFormattingParams> {
3198        Ok(lsp::DocumentOnTypeFormattingParams {
3199            text_document_position: make_lsp_text_document_position(path, self.position)?,
3200            ch: self.trigger.clone(),
3201            options: self.options.clone(),
3202        })
3203    }
3204
3205    async fn response_from_lsp(
3206        self,
3207        message: Option<Vec<lsp::TextEdit>>,
3208        lsp_store: Entity<LspStore>,
3209        buffer: Entity<Buffer>,
3210        server_id: LanguageServerId,
3211        mut cx: AsyncApp,
3212    ) -> Result<Option<Transaction>> {
3213        if let Some(edits) = message {
3214            let (lsp_adapter, lsp_server) =
3215                language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
3216            LocalLspStore::deserialize_text_edits(
3217                lsp_store,
3218                buffer,
3219                edits,
3220                self.push_to_history,
3221                lsp_adapter,
3222                lsp_server,
3223                &mut cx,
3224            )
3225            .await
3226        } else {
3227            Ok(None)
3228        }
3229    }
3230
3231    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::OnTypeFormatting {
3232        proto::OnTypeFormatting {
3233            project_id,
3234            buffer_id: buffer.remote_id().into(),
3235            position: Some(language::proto::serialize_anchor(
3236                &buffer.anchor_before(self.position),
3237            )),
3238            trigger: self.trigger.clone(),
3239            version: serialize_version(&buffer.version()),
3240        }
3241    }
3242
3243    async fn from_proto(
3244        message: proto::OnTypeFormatting,
3245        _: Entity<LspStore>,
3246        buffer: Entity<Buffer>,
3247        mut cx: AsyncApp,
3248    ) -> Result<Self> {
3249        let position = message
3250            .position
3251            .and_then(deserialize_anchor)
3252            .context("invalid position")?;
3253        buffer
3254            .update(&mut cx, |buffer, _| {
3255                buffer.wait_for_version(deserialize_version(&message.version))
3256            })
3257            .await?;
3258
3259        let options = buffer.update(&mut cx, |buffer, cx| {
3260            lsp_formatting_options(LanguageSettings::for_buffer(buffer, cx).as_ref())
3261        });
3262
3263        Ok(Self {
3264            position: buffer.read_with(&cx, |buffer, _| position.to_point_utf16(buffer)),
3265            trigger: message.trigger.clone(),
3266            options,
3267            push_to_history: false,
3268        })
3269    }
3270
3271    fn response_to_proto(
3272        response: Option<Transaction>,
3273        _: &mut LspStore,
3274        _: PeerId,
3275        _: &clock::Global,
3276        _: &mut App,
3277    ) -> proto::OnTypeFormattingResponse {
3278        proto::OnTypeFormattingResponse {
3279            transaction: response
3280                .map(|transaction| language::proto::serialize_transaction(&transaction)),
3281        }
3282    }
3283
3284    async fn response_from_proto(
3285        self,
3286        message: proto::OnTypeFormattingResponse,
3287        _: Entity<LspStore>,
3288        _: Entity<Buffer>,
3289        _: AsyncApp,
3290    ) -> Result<Option<Transaction>> {
3291        let Some(transaction) = message.transaction else {
3292            return Ok(None);
3293        };
3294        Ok(Some(language::proto::deserialize_transaction(transaction)?))
3295    }
3296
3297    fn buffer_id_from_proto(message: &proto::OnTypeFormatting) -> Result<BufferId> {
3298        BufferId::new(message.buffer_id)
3299    }
3300}
3301
3302impl InlayHints {
3303    pub async fn lsp_to_project_hint(
3304        lsp_hint: lsp::InlayHint,
3305        buffer_handle: &Entity<Buffer>,
3306        server_id: LanguageServerId,
3307        resolve_state: ResolveState,
3308        force_no_type_left_padding: bool,
3309        cx: &mut AsyncApp,
3310    ) -> anyhow::Result<InlayHint> {
3311        let kind = lsp_hint.kind.and_then(|kind| match kind {
3312            lsp::InlayHintKind::TYPE => Some(InlayHintKind::Type),
3313            lsp::InlayHintKind::PARAMETER => Some(InlayHintKind::Parameter),
3314            _ => None,
3315        });
3316
3317        let position = buffer_handle.read_with(cx, |buffer, _| {
3318            let position = buffer.clip_point_utf16(point_from_lsp(lsp_hint.position), Bias::Left);
3319            if kind == Some(InlayHintKind::Parameter) {
3320                buffer.anchor_before(position)
3321            } else {
3322                buffer.anchor_after(position)
3323            }
3324        });
3325        let label = Self::lsp_inlay_label_to_project(lsp_hint.label, server_id)
3326            .await
3327            .context("lsp to project inlay hint conversion")?;
3328        let padding_left = if force_no_type_left_padding && kind == Some(InlayHintKind::Type) {
3329            false
3330        } else {
3331            lsp_hint.padding_left.unwrap_or(false)
3332        };
3333
3334        Ok(InlayHint {
3335            position,
3336            padding_left,
3337            padding_right: lsp_hint.padding_right.unwrap_or(false),
3338            label,
3339            kind,
3340            tooltip: lsp_hint.tooltip.map(|tooltip| match tooltip {
3341                lsp::InlayHintTooltip::String(s) => InlayHintTooltip::String(s),
3342                lsp::InlayHintTooltip::MarkupContent(markup_content) => {
3343                    InlayHintTooltip::MarkupContent(MarkupContent {
3344                        kind: match markup_content.kind {
3345                            lsp::MarkupKind::PlainText => HoverBlockKind::PlainText,
3346                            lsp::MarkupKind::Markdown => HoverBlockKind::Markdown,
3347                        },
3348                        value: markup_content.value,
3349                    })
3350                }
3351            }),
3352            resolve_state,
3353        })
3354    }
3355
3356    async fn lsp_inlay_label_to_project(
3357        lsp_label: lsp::InlayHintLabel,
3358        server_id: LanguageServerId,
3359    ) -> anyhow::Result<InlayHintLabel> {
3360        let label = match lsp_label {
3361            lsp::InlayHintLabel::String(s) => InlayHintLabel::String(s),
3362            lsp::InlayHintLabel::LabelParts(lsp_parts) => {
3363                let mut parts = Vec::with_capacity(lsp_parts.len());
3364                for lsp_part in lsp_parts {
3365                    parts.push(InlayHintLabelPart {
3366                        value: lsp_part.value,
3367                        tooltip: lsp_part.tooltip.map(|tooltip| match tooltip {
3368                            lsp::InlayHintLabelPartTooltip::String(s) => {
3369                                InlayHintLabelPartTooltip::String(s)
3370                            }
3371                            lsp::InlayHintLabelPartTooltip::MarkupContent(markup_content) => {
3372                                InlayHintLabelPartTooltip::MarkupContent(MarkupContent {
3373                                    kind: match markup_content.kind {
3374                                        lsp::MarkupKind::PlainText => HoverBlockKind::PlainText,
3375                                        lsp::MarkupKind::Markdown => HoverBlockKind::Markdown,
3376                                    },
3377                                    value: markup_content.value,
3378                                })
3379                            }
3380                        }),
3381                        location: Some(server_id).zip(lsp_part.location),
3382                    });
3383                }
3384                InlayHintLabel::LabelParts(parts)
3385            }
3386        };
3387
3388        Ok(label)
3389    }
3390
3391    pub fn project_to_proto_hint(response_hint: InlayHint) -> proto::InlayHint {
3392        let (state, lsp_resolve_state) = match response_hint.resolve_state {
3393            ResolveState::Resolved => (0, None),
3394            ResolveState::CanResolve(server_id, resolve_data) => (
3395                1,
3396                Some(proto::resolve_state::LspResolveState {
3397                    server_id: server_id.0 as u64,
3398                    value: resolve_data.map(|json_data| {
3399                        serde_json::to_string(&json_data)
3400                            .expect("failed to serialize resolve json data")
3401                    }),
3402                }),
3403            ),
3404            ResolveState::Resolving => (2, None),
3405        };
3406        let resolve_state = Some(proto::ResolveState {
3407            state,
3408            lsp_resolve_state,
3409        });
3410        proto::InlayHint {
3411            position: Some(language::proto::serialize_anchor(&response_hint.position)),
3412            padding_left: response_hint.padding_left,
3413            padding_right: response_hint.padding_right,
3414            label: Some(proto::InlayHintLabel {
3415                label: Some(match response_hint.label {
3416                    InlayHintLabel::String(s) => proto::inlay_hint_label::Label::Value(s),
3417                    InlayHintLabel::LabelParts(label_parts) => {
3418                        proto::inlay_hint_label::Label::LabelParts(proto::InlayHintLabelParts {
3419                            parts: label_parts.into_iter().map(|label_part| {
3420                                let location_url = label_part.location.as_ref().map(|(_, location)| location.uri.to_string());
3421                                let location_range_start = label_part.location.as_ref().map(|(_, location)| point_from_lsp(location.range.start).0).map(|point| proto::PointUtf16 { row: point.row, column: point.column });
3422                                let location_range_end = label_part.location.as_ref().map(|(_, location)| point_from_lsp(location.range.end).0).map(|point| proto::PointUtf16 { row: point.row, column: point.column });
3423                                proto::InlayHintLabelPart {
3424                                value: label_part.value,
3425                                tooltip: label_part.tooltip.map(|tooltip| {
3426                                    let proto_tooltip = match tooltip {
3427                                        InlayHintLabelPartTooltip::String(s) => proto::inlay_hint_label_part_tooltip::Content::Value(s),
3428                                        InlayHintLabelPartTooltip::MarkupContent(markup_content) => proto::inlay_hint_label_part_tooltip::Content::MarkupContent(proto::MarkupContent {
3429                                            is_markdown: markup_content.kind == HoverBlockKind::Markdown,
3430                                            value: markup_content.value,
3431                                        }),
3432                                    };
3433                                    proto::InlayHintLabelPartTooltip {content: Some(proto_tooltip)}
3434                                }),
3435                                location_url,
3436                                location_range_start,
3437                                location_range_end,
3438                                language_server_id: label_part.location.as_ref().map(|(server_id, _)| server_id.0 as u64),
3439                            }}).collect()
3440                        })
3441                    }
3442                }),
3443            }),
3444            kind: response_hint.kind.map(|kind| kind.name().to_string()),
3445            tooltip: response_hint.tooltip.map(|response_tooltip| {
3446                let proto_tooltip = match response_tooltip {
3447                    InlayHintTooltip::String(s) => proto::inlay_hint_tooltip::Content::Value(s),
3448                    InlayHintTooltip::MarkupContent(markup_content) => {
3449                        proto::inlay_hint_tooltip::Content::MarkupContent(proto::MarkupContent {
3450                            is_markdown: markup_content.kind == HoverBlockKind::Markdown,
3451                            value: markup_content.value,
3452                        })
3453                    }
3454                };
3455                proto::InlayHintTooltip {
3456                    content: Some(proto_tooltip),
3457                }
3458            }),
3459            resolve_state,
3460        }
3461    }
3462
3463    pub fn proto_to_project_hint(message_hint: proto::InlayHint) -> anyhow::Result<InlayHint> {
3464        let resolve_state = message_hint.resolve_state.as_ref().unwrap_or_else(|| {
3465            panic!("incorrect proto inlay hint message: no resolve state in hint {message_hint:?}",)
3466        });
3467        let resolve_state_data = resolve_state
3468            .lsp_resolve_state.as_ref()
3469            .map(|lsp_resolve_state| {
3470                let value = lsp_resolve_state.value.as_deref().map(|value| {
3471                    serde_json::from_str::<Option<lsp::LSPAny>>(value)
3472                        .with_context(|| format!("incorrect proto inlay hint message: non-json resolve state {lsp_resolve_state:?}"))
3473                }).transpose()?.flatten();
3474                anyhow::Ok((LanguageServerId(lsp_resolve_state.server_id as usize), value))
3475            })
3476            .transpose()?;
3477        let resolve_state = match resolve_state.state {
3478            0 => ResolveState::Resolved,
3479            1 => {
3480                let (server_id, lsp_resolve_state) = resolve_state_data.with_context(|| {
3481                    format!(
3482                        "No lsp resolve data for the hint that can be resolved: {message_hint:?}"
3483                    )
3484                })?;
3485                ResolveState::CanResolve(server_id, lsp_resolve_state)
3486            }
3487            2 => ResolveState::Resolving,
3488            invalid => {
3489                anyhow::bail!("Unexpected resolve state {invalid} for hint {message_hint:?}")
3490            }
3491        };
3492        Ok(InlayHint {
3493            position: message_hint
3494                .position
3495                .and_then(language::proto::deserialize_anchor)
3496                .context("invalid position")?,
3497            label: match message_hint
3498                .label
3499                .and_then(|label| label.label)
3500                .context("missing label")?
3501            {
3502                proto::inlay_hint_label::Label::Value(s) => InlayHintLabel::String(s),
3503                proto::inlay_hint_label::Label::LabelParts(parts) => {
3504                    let mut label_parts = Vec::new();
3505                    for part in parts.parts {
3506                        label_parts.push(InlayHintLabelPart {
3507                            value: part.value,
3508                            tooltip: part.tooltip.map(|tooltip| match tooltip.content {
3509                                Some(proto::inlay_hint_label_part_tooltip::Content::Value(s)) => {
3510                                    InlayHintLabelPartTooltip::String(s)
3511                                }
3512                                Some(
3513                                    proto::inlay_hint_label_part_tooltip::Content::MarkupContent(
3514                                        markup_content,
3515                                    ),
3516                                ) => InlayHintLabelPartTooltip::MarkupContent(MarkupContent {
3517                                    kind: if markup_content.is_markdown {
3518                                        HoverBlockKind::Markdown
3519                                    } else {
3520                                        HoverBlockKind::PlainText
3521                                    },
3522                                    value: markup_content.value,
3523                                }),
3524                                None => InlayHintLabelPartTooltip::String(String::new()),
3525                            }),
3526                            location: {
3527                                match part
3528                                    .location_url
3529                                    .zip(
3530                                        part.location_range_start.and_then(|start| {
3531                                            Some(start..part.location_range_end?)
3532                                        }),
3533                                    )
3534                                    .zip(part.language_server_id)
3535                                {
3536                                    Some(((uri, range), server_id)) => Some((
3537                                        LanguageServerId(server_id as usize),
3538                                        lsp::Location {
3539                                            uri: lsp::Uri::from_str(&uri).with_context(|| {
3540                                                format!("invalid uri in hint part {uri:?}")
3541                                            })?,
3542                                            range: lsp::Range::new(
3543                                                point_to_lsp(PointUtf16::new(
3544                                                    range.start.row,
3545                                                    range.start.column,
3546                                                )),
3547                                                point_to_lsp(PointUtf16::new(
3548                                                    range.end.row,
3549                                                    range.end.column,
3550                                                )),
3551                                            ),
3552                                        },
3553                                    )),
3554                                    None => None,
3555                                }
3556                            },
3557                        });
3558                    }
3559
3560                    InlayHintLabel::LabelParts(label_parts)
3561                }
3562            },
3563            padding_left: message_hint.padding_left,
3564            padding_right: message_hint.padding_right,
3565            kind: message_hint
3566                .kind
3567                .as_deref()
3568                .and_then(InlayHintKind::from_name),
3569            tooltip: message_hint.tooltip.and_then(|tooltip| {
3570                Some(match tooltip.content? {
3571                    proto::inlay_hint_tooltip::Content::Value(s) => InlayHintTooltip::String(s),
3572                    proto::inlay_hint_tooltip::Content::MarkupContent(markup_content) => {
3573                        InlayHintTooltip::MarkupContent(MarkupContent {
3574                            kind: if markup_content.is_markdown {
3575                                HoverBlockKind::Markdown
3576                            } else {
3577                                HoverBlockKind::PlainText
3578                            },
3579                            value: markup_content.value,
3580                        })
3581                    }
3582                })
3583            }),
3584            resolve_state,
3585        })
3586    }
3587
3588    pub fn project_to_lsp_hint(hint: InlayHint, snapshot: &BufferSnapshot) -> lsp::InlayHint {
3589        lsp::InlayHint {
3590            position: point_to_lsp(hint.position.to_point_utf16(snapshot)),
3591            kind: hint.kind.map(|kind| match kind {
3592                InlayHintKind::Type => lsp::InlayHintKind::TYPE,
3593                InlayHintKind::Parameter => lsp::InlayHintKind::PARAMETER,
3594            }),
3595            text_edits: None,
3596            tooltip: hint.tooltip.and_then(|tooltip| {
3597                Some(match tooltip {
3598                    InlayHintTooltip::String(s) => lsp::InlayHintTooltip::String(s),
3599                    InlayHintTooltip::MarkupContent(markup_content) => {
3600                        lsp::InlayHintTooltip::MarkupContent(lsp::MarkupContent {
3601                            kind: match markup_content.kind {
3602                                HoverBlockKind::PlainText => lsp::MarkupKind::PlainText,
3603                                HoverBlockKind::Markdown => lsp::MarkupKind::Markdown,
3604                                HoverBlockKind::Code { .. } => return None,
3605                            },
3606                            value: markup_content.value,
3607                        })
3608                    }
3609                })
3610            }),
3611            label: match hint.label {
3612                InlayHintLabel::String(s) => lsp::InlayHintLabel::String(s),
3613                InlayHintLabel::LabelParts(label_parts) => lsp::InlayHintLabel::LabelParts(
3614                    label_parts
3615                        .into_iter()
3616                        .map(|part| lsp::InlayHintLabelPart {
3617                            value: part.value,
3618                            tooltip: part.tooltip.and_then(|tooltip| {
3619                                Some(match tooltip {
3620                                    InlayHintLabelPartTooltip::String(s) => {
3621                                        lsp::InlayHintLabelPartTooltip::String(s)
3622                                    }
3623                                    InlayHintLabelPartTooltip::MarkupContent(markup_content) => {
3624                                        lsp::InlayHintLabelPartTooltip::MarkupContent(
3625                                            lsp::MarkupContent {
3626                                                kind: match markup_content.kind {
3627                                                    HoverBlockKind::PlainText => {
3628                                                        lsp::MarkupKind::PlainText
3629                                                    }
3630                                                    HoverBlockKind::Markdown => {
3631                                                        lsp::MarkupKind::Markdown
3632                                                    }
3633                                                    HoverBlockKind::Code { .. } => return None,
3634                                                },
3635                                                value: markup_content.value,
3636                                            },
3637                                        )
3638                                    }
3639                                })
3640                            }),
3641                            location: part.location.map(|(_, location)| location),
3642                            command: None,
3643                        })
3644                        .collect(),
3645                ),
3646            },
3647            padding_left: Some(hint.padding_left),
3648            padding_right: Some(hint.padding_right),
3649            data: match hint.resolve_state {
3650                ResolveState::CanResolve(_, data) => data,
3651                ResolveState::Resolving | ResolveState::Resolved => None,
3652            },
3653        }
3654    }
3655
3656    pub fn can_resolve_inlays(capabilities: &ServerCapabilities) -> bool {
3657        capabilities
3658            .inlay_hint_provider
3659            .as_ref()
3660            .and_then(|options| match options {
3661                OneOf::Left(_is_supported) => None,
3662                OneOf::Right(capabilities) => match capabilities {
3663                    lsp::InlayHintServerCapabilities::Options(o) => o.resolve_provider,
3664                    lsp::InlayHintServerCapabilities::RegistrationOptions(o) => {
3665                        o.inlay_hint_options.resolve_provider
3666                    }
3667                },
3668            })
3669            .unwrap_or(false)
3670    }
3671
3672    pub fn check_capabilities(capabilities: &ServerCapabilities) -> bool {
3673        capabilities
3674            .inlay_hint_provider
3675            .as_ref()
3676            .is_some_and(|inlay_hint_provider| match inlay_hint_provider {
3677                lsp::OneOf::Left(enabled) => *enabled,
3678                lsp::OneOf::Right(_) => true,
3679            })
3680    }
3681}
3682
3683#[async_trait(?Send)]
3684impl LspCommand for InlayHints {
3685    type Response = Vec<InlayHint>;
3686    type LspRequest = lsp::InlayHintRequest;
3687    type ProtoRequest = proto::InlayHints;
3688
3689    fn display_name(&self) -> &str {
3690        "Inlay hints"
3691    }
3692
3693    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
3694        Self::check_capabilities(&capabilities.server_capabilities)
3695    }
3696
3697    fn to_lsp(
3698        &self,
3699        path: &Path,
3700        buffer: &Buffer,
3701        _: &Arc<LanguageServer>,
3702        _: &App,
3703    ) -> Result<lsp::InlayHintParams> {
3704        Ok(lsp::InlayHintParams {
3705            text_document: lsp::TextDocumentIdentifier {
3706                uri: file_path_to_lsp_url(path)?,
3707            },
3708            range: range_to_lsp(self.range.to_point_utf16(buffer))?,
3709            work_done_progress_params: Default::default(),
3710        })
3711    }
3712
3713    async fn response_from_lsp(
3714        self,
3715        message: Option<Vec<lsp::InlayHint>>,
3716        lsp_store: Entity<LspStore>,
3717        buffer: Entity<Buffer>,
3718        server_id: LanguageServerId,
3719        mut cx: AsyncApp,
3720    ) -> anyhow::Result<Vec<InlayHint>> {
3721        let (lsp_adapter, lsp_server) =
3722            language_server_for_buffer(&lsp_store, &buffer, server_id, &mut cx)?;
3723        // `typescript-language-server` adds padding to the left for type hints, turning
3724        // `const foo: boolean` into `const foo : boolean` which looks odd.
3725        // `rust-analyzer` does not have the padding for this case, and we have to accommodate both.
3726        //
3727        // We could trim the whole string, but being pessimistic on par with the situation above,
3728        // there might be a hint with multiple whitespaces at the end(s) which we need to display properly.
3729        // Hence let's use a heuristic first to handle the most awkward case and look for more.
3730        let force_no_type_left_padding =
3731            lsp_adapter.name.0.as_ref() == "typescript-language-server";
3732
3733        let hints = message.unwrap_or_default().into_iter().map(|lsp_hint| {
3734            let resolve_state = if InlayHints::can_resolve_inlays(&lsp_server.capabilities()) {
3735                ResolveState::CanResolve(lsp_server.server_id(), lsp_hint.data.clone())
3736            } else {
3737                ResolveState::Resolved
3738            };
3739
3740            let buffer = buffer.clone();
3741            cx.spawn(async move |cx| {
3742                InlayHints::lsp_to_project_hint(
3743                    lsp_hint,
3744                    &buffer,
3745                    server_id,
3746                    resolve_state,
3747                    force_no_type_left_padding,
3748                    cx,
3749                )
3750                .await
3751            })
3752        });
3753        future::join_all(hints)
3754            .await
3755            .into_iter()
3756            .collect::<anyhow::Result<_>>()
3757            .context("lsp to project inlay hints conversion")
3758    }
3759
3760    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::InlayHints {
3761        proto::InlayHints {
3762            project_id,
3763            buffer_id: buffer.remote_id().into(),
3764            start: Some(language::proto::serialize_anchor(&self.range.start)),
3765            end: Some(language::proto::serialize_anchor(&self.range.end)),
3766            version: serialize_version(&buffer.version()),
3767        }
3768    }
3769
3770    async fn from_proto(
3771        message: proto::InlayHints,
3772        _: Entity<LspStore>,
3773        buffer: Entity<Buffer>,
3774        mut cx: AsyncApp,
3775    ) -> Result<Self> {
3776        let start = message
3777            .start
3778            .and_then(language::proto::deserialize_anchor)
3779            .context("invalid start")?;
3780        let end = message
3781            .end
3782            .and_then(language::proto::deserialize_anchor)
3783            .context("invalid end")?;
3784        buffer
3785            .update(&mut cx, |buffer, _| {
3786                buffer.wait_for_version(deserialize_version(&message.version))
3787            })
3788            .await?;
3789
3790        Ok(Self { range: start..end })
3791    }
3792
3793    fn response_to_proto(
3794        response: Vec<InlayHint>,
3795        _: &mut LspStore,
3796        _: PeerId,
3797        buffer_version: &clock::Global,
3798        _: &mut App,
3799    ) -> proto::InlayHintsResponse {
3800        proto::InlayHintsResponse {
3801            hints: response
3802                .into_iter()
3803                .map(InlayHints::project_to_proto_hint)
3804                .collect(),
3805            version: serialize_version(buffer_version),
3806        }
3807    }
3808
3809    async fn response_from_proto(
3810        self,
3811        message: proto::InlayHintsResponse,
3812        _: Entity<LspStore>,
3813        buffer: Entity<Buffer>,
3814        mut cx: AsyncApp,
3815    ) -> anyhow::Result<Vec<InlayHint>> {
3816        buffer
3817            .update(&mut cx, |buffer, _| {
3818                buffer.wait_for_version(deserialize_version(&message.version))
3819            })
3820            .await?;
3821
3822        let mut hints = Vec::new();
3823        for message_hint in message.hints {
3824            hints.push(InlayHints::proto_to_project_hint(message_hint)?);
3825        }
3826
3827        Ok(hints)
3828    }
3829
3830    fn buffer_id_from_proto(message: &proto::InlayHints) -> Result<BufferId> {
3831        BufferId::new(message.buffer_id)
3832    }
3833}
3834
3835#[async_trait(?Send)]
3836impl LspCommand for SemanticTokensFull {
3837    type Response = SemanticTokensResponse;
3838    type LspRequest = lsp::SemanticTokensFullRequest;
3839    type ProtoRequest = proto::SemanticTokens;
3840
3841    fn display_name(&self) -> &str {
3842        "Semantic tokens full"
3843    }
3844
3845    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
3846        capabilities
3847            .server_capabilities
3848            .semantic_tokens_provider
3849            .as_ref()
3850            .is_some_and(|semantic_tokens_provider| {
3851                let options = match semantic_tokens_provider {
3852                    lsp::SemanticTokensServerCapabilities::SemanticTokensOptions(opts) => opts,
3853                    lsp::SemanticTokensServerCapabilities::SemanticTokensRegistrationOptions(
3854                        opts,
3855                    ) => &opts.semantic_tokens_options,
3856                };
3857
3858                match options.full {
3859                    Some(lsp::SemanticTokensFullOptions::Bool(is_supported)) => is_supported,
3860                    Some(lsp::SemanticTokensFullOptions::Delta { .. }) => true,
3861                    None => false,
3862                }
3863            })
3864    }
3865
3866    fn to_lsp(
3867        &self,
3868        path: &Path,
3869        _: &Buffer,
3870        _: &Arc<LanguageServer>,
3871        _: &App,
3872    ) -> Result<lsp::SemanticTokensParams> {
3873        Ok(lsp::SemanticTokensParams {
3874            text_document: lsp::TextDocumentIdentifier {
3875                uri: file_path_to_lsp_url(path)?,
3876            },
3877            partial_result_params: Default::default(),
3878            work_done_progress_params: Default::default(),
3879        })
3880    }
3881
3882    async fn response_from_lsp(
3883        self,
3884        message: Option<lsp::SemanticTokensResult>,
3885        _: Entity<LspStore>,
3886        _: Entity<Buffer>,
3887        _: LanguageServerId,
3888        _: AsyncApp,
3889    ) -> anyhow::Result<SemanticTokensResponse> {
3890        match message {
3891            Some(lsp::SemanticTokensResult::Tokens(tokens)) => Ok(SemanticTokensResponse::Full {
3892                data: tokens.data,
3893                result_id: tokens.result_id.map(SharedString::new),
3894            }),
3895            Some(lsp::SemanticTokensResult::Partial(_)) => {
3896                anyhow::bail!(
3897                    "Unexpected semantic tokens response with partial result for inlay hints"
3898                )
3899            }
3900            None => Ok(Default::default()),
3901        }
3902    }
3903
3904    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::SemanticTokens {
3905        proto::SemanticTokens {
3906            project_id,
3907            buffer_id: buffer.remote_id().into(),
3908            version: serialize_version(&buffer.version()),
3909            for_server: self.for_server.map(|id| id.to_proto()),
3910        }
3911    }
3912
3913    async fn from_proto(
3914        message: proto::SemanticTokens,
3915        _: Entity<LspStore>,
3916        buffer: Entity<Buffer>,
3917        mut cx: AsyncApp,
3918    ) -> Result<Self> {
3919        buffer
3920            .update(&mut cx, |buffer, _| {
3921                buffer.wait_for_version(deserialize_version(&message.version))
3922            })
3923            .await?;
3924
3925        Ok(Self {
3926            for_server: message
3927                .for_server
3928                .map(|id| LanguageServerId::from_proto(id)),
3929        })
3930    }
3931
3932    fn response_to_proto(
3933        response: SemanticTokensResponse,
3934        _: &mut LspStore,
3935        _: PeerId,
3936        buffer_version: &clock::Global,
3937        _: &mut App,
3938    ) -> proto::SemanticTokensResponse {
3939        match response {
3940            SemanticTokensResponse::Full { data, result_id } => proto::SemanticTokensResponse {
3941                data,
3942                edits: Vec::new(),
3943                result_id: result_id.map(|s| s.to_string()),
3944                version: serialize_version(buffer_version),
3945            },
3946            SemanticTokensResponse::Delta { edits, result_id } => proto::SemanticTokensResponse {
3947                data: Vec::new(),
3948                edits: edits
3949                    .into_iter()
3950                    .map(|edit| proto::SemanticTokensEdit {
3951                        start: edit.start,
3952                        delete_count: edit.delete_count,
3953                        data: edit.data,
3954                    })
3955                    .collect(),
3956                result_id: result_id.map(|s| s.to_string()),
3957                version: serialize_version(buffer_version),
3958            },
3959        }
3960    }
3961
3962    async fn response_from_proto(
3963        self,
3964        message: proto::SemanticTokensResponse,
3965        _: Entity<LspStore>,
3966        buffer: Entity<Buffer>,
3967        mut cx: AsyncApp,
3968    ) -> anyhow::Result<SemanticTokensResponse> {
3969        buffer
3970            .update(&mut cx, |buffer, _| {
3971                buffer.wait_for_version(deserialize_version(&message.version))
3972            })
3973            .await?;
3974
3975        Ok(SemanticTokensResponse::Full {
3976            data: message.data,
3977            result_id: message.result_id.map(SharedString::new),
3978        })
3979    }
3980
3981    fn buffer_id_from_proto(message: &proto::SemanticTokens) -> Result<BufferId> {
3982        BufferId::new(message.buffer_id)
3983    }
3984}
3985
3986#[async_trait(?Send)]
3987impl LspCommand for SemanticTokensDelta {
3988    type Response = SemanticTokensResponse;
3989    type LspRequest = lsp::SemanticTokensFullDeltaRequest;
3990    type ProtoRequest = proto::SemanticTokens;
3991
3992    fn display_name(&self) -> &str {
3993        "Semantic tokens delta"
3994    }
3995
3996    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
3997        capabilities
3998            .server_capabilities
3999            .semantic_tokens_provider
4000            .as_ref()
4001            .is_some_and(|semantic_tokens_provider| {
4002                let options = match semantic_tokens_provider {
4003                    lsp::SemanticTokensServerCapabilities::SemanticTokensOptions(opts) => opts,
4004                    lsp::SemanticTokensServerCapabilities::SemanticTokensRegistrationOptions(
4005                        opts,
4006                    ) => &opts.semantic_tokens_options,
4007                };
4008
4009                match options.full {
4010                    Some(lsp::SemanticTokensFullOptions::Delta { delta }) => delta.unwrap_or(false),
4011                    // `full: true` (instead of `full: { delta: true }`) means no support for delta.
4012                    _ => false,
4013                }
4014            })
4015    }
4016
4017    fn to_lsp(
4018        &self,
4019        path: &Path,
4020        _: &Buffer,
4021        _: &Arc<LanguageServer>,
4022        _: &App,
4023    ) -> Result<lsp::SemanticTokensDeltaParams> {
4024        Ok(lsp::SemanticTokensDeltaParams {
4025            text_document: lsp::TextDocumentIdentifier {
4026                uri: file_path_to_lsp_url(path)?,
4027            },
4028            previous_result_id: self.previous_result_id.clone().map(|s| s.to_string()),
4029            partial_result_params: Default::default(),
4030            work_done_progress_params: Default::default(),
4031        })
4032    }
4033
4034    async fn response_from_lsp(
4035        self,
4036        message: Option<lsp::SemanticTokensFullDeltaResult>,
4037        _: Entity<LspStore>,
4038        _: Entity<Buffer>,
4039        _: LanguageServerId,
4040        _: AsyncApp,
4041    ) -> anyhow::Result<SemanticTokensResponse> {
4042        match message {
4043            Some(lsp::SemanticTokensFullDeltaResult::Tokens(tokens)) => {
4044                Ok(SemanticTokensResponse::Full {
4045                    data: tokens.data,
4046                    result_id: tokens.result_id.map(SharedString::new),
4047                })
4048            }
4049            Some(lsp::SemanticTokensFullDeltaResult::TokensDelta(delta)) => {
4050                Ok(SemanticTokensResponse::Delta {
4051                    edits: delta
4052                        .edits
4053                        .into_iter()
4054                        .map(|e| SemanticTokensEdit {
4055                            start: e.start,
4056                            delete_count: e.delete_count,
4057                            data: e.data.unwrap_or_default(),
4058                        })
4059                        .collect(),
4060                    result_id: delta.result_id.map(SharedString::new),
4061                })
4062            }
4063            Some(lsp::SemanticTokensFullDeltaResult::PartialTokensDelta { .. }) => {
4064                anyhow::bail!(
4065                    "Unexpected semantic tokens response with partial result for inlay hints"
4066                )
4067            }
4068            None => Ok(Default::default()),
4069        }
4070    }
4071
4072    fn to_proto(&self, _: u64, _: &Buffer) -> proto::SemanticTokens {
4073        unimplemented!("Delta requests are never initialted on the remote client side")
4074    }
4075
4076    async fn from_proto(
4077        _: proto::SemanticTokens,
4078        _: Entity<LspStore>,
4079        _: Entity<Buffer>,
4080        _: AsyncApp,
4081    ) -> Result<Self> {
4082        unimplemented!("Delta requests are never initialted on the remote client side")
4083    }
4084
4085    fn response_to_proto(
4086        response: SemanticTokensResponse,
4087        _: &mut LspStore,
4088        _: PeerId,
4089        buffer_version: &clock::Global,
4090        _: &mut App,
4091    ) -> proto::SemanticTokensResponse {
4092        match response {
4093            SemanticTokensResponse::Full { data, result_id } => proto::SemanticTokensResponse {
4094                data,
4095                edits: Vec::new(),
4096                result_id: result_id.map(|s| s.to_string()),
4097                version: serialize_version(buffer_version),
4098            },
4099            SemanticTokensResponse::Delta { edits, result_id } => proto::SemanticTokensResponse {
4100                data: Vec::new(),
4101                edits: edits
4102                    .into_iter()
4103                    .map(|edit| proto::SemanticTokensEdit {
4104                        start: edit.start,
4105                        delete_count: edit.delete_count,
4106                        data: edit.data,
4107                    })
4108                    .collect(),
4109                result_id: result_id.map(|s| s.to_string()),
4110                version: serialize_version(buffer_version),
4111            },
4112        }
4113    }
4114
4115    async fn response_from_proto(
4116        self,
4117        message: proto::SemanticTokensResponse,
4118        _: Entity<LspStore>,
4119        buffer: Entity<Buffer>,
4120        mut cx: AsyncApp,
4121    ) -> anyhow::Result<SemanticTokensResponse> {
4122        buffer
4123            .update(&mut cx, |buffer, _| {
4124                buffer.wait_for_version(deserialize_version(&message.version))
4125            })
4126            .await?;
4127
4128        Ok(SemanticTokensResponse::Full {
4129            data: message.data,
4130            result_id: message.result_id.map(SharedString::new),
4131        })
4132    }
4133
4134    fn buffer_id_from_proto(message: &proto::SemanticTokens) -> Result<BufferId> {
4135        BufferId::new(message.buffer_id)
4136    }
4137}
4138
4139#[async_trait(?Send)]
4140impl LspCommand for GetCodeLens {
4141    type Response = Vec<CodeAction>;
4142    type LspRequest = lsp::CodeLensRequest;
4143    type ProtoRequest = proto::GetCodeLens;
4144
4145    fn display_name(&self) -> &str {
4146        "Code Lens"
4147    }
4148
4149    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
4150        capabilities
4151            .server_capabilities
4152            .code_lens_provider
4153            .is_some()
4154    }
4155
4156    fn to_lsp(
4157        &self,
4158        path: &Path,
4159        _: &Buffer,
4160        _: &Arc<LanguageServer>,
4161        _: &App,
4162    ) -> Result<lsp::CodeLensParams> {
4163        Ok(lsp::CodeLensParams {
4164            text_document: lsp::TextDocumentIdentifier {
4165                uri: file_path_to_lsp_url(path)?,
4166            },
4167            work_done_progress_params: lsp::WorkDoneProgressParams::default(),
4168            partial_result_params: lsp::PartialResultParams::default(),
4169        })
4170    }
4171
4172    async fn response_from_lsp(
4173        self,
4174        message: Option<Vec<lsp::CodeLens>>,
4175        _lsp_store: Entity<LspStore>,
4176        buffer: Entity<Buffer>,
4177        server_id: LanguageServerId,
4178        cx: AsyncApp,
4179    ) -> anyhow::Result<Vec<CodeAction>> {
4180        let snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot());
4181        let code_lenses = message.unwrap_or_default();
4182
4183        Ok(code_lenses
4184            .into_iter()
4185            .map(|code_lens| {
4186                let code_lens_range = range_from_lsp(code_lens.range);
4187                let start = snapshot.clip_point_utf16(code_lens_range.start, Bias::Left);
4188                let end = snapshot.clip_point_utf16(code_lens_range.end, Bias::Right);
4189                let range = snapshot.anchor_before(start)..snapshot.anchor_after(end);
4190                let resolved = code_lens.command.is_some();
4191                CodeAction {
4192                    server_id,
4193                    range,
4194                    lsp_action: LspAction::CodeLens(code_lens),
4195                    resolved,
4196                }
4197            })
4198            .collect())
4199    }
4200
4201    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetCodeLens {
4202        proto::GetCodeLens {
4203            project_id,
4204            buffer_id: buffer.remote_id().into(),
4205            version: serialize_version(&buffer.version()),
4206        }
4207    }
4208
4209    async fn from_proto(
4210        message: proto::GetCodeLens,
4211        _: Entity<LspStore>,
4212        buffer: Entity<Buffer>,
4213        mut cx: AsyncApp,
4214    ) -> Result<Self> {
4215        buffer
4216            .update(&mut cx, |buffer, _| {
4217                buffer.wait_for_version(deserialize_version(&message.version))
4218            })
4219            .await?;
4220        Ok(Self)
4221    }
4222
4223    fn response_to_proto(
4224        response: Vec<CodeAction>,
4225        _: &mut LspStore,
4226        _: PeerId,
4227        buffer_version: &clock::Global,
4228        _: &mut App,
4229    ) -> proto::GetCodeLensResponse {
4230        proto::GetCodeLensResponse {
4231            lens_actions: response
4232                .iter()
4233                .map(LspStore::serialize_code_action)
4234                .collect(),
4235            version: serialize_version(buffer_version),
4236        }
4237    }
4238
4239    async fn response_from_proto(
4240        self,
4241        message: proto::GetCodeLensResponse,
4242        _: Entity<LspStore>,
4243        buffer: Entity<Buffer>,
4244        mut cx: AsyncApp,
4245    ) -> anyhow::Result<Vec<CodeAction>> {
4246        buffer
4247            .update(&mut cx, |buffer, _| {
4248                buffer.wait_for_version(deserialize_version(&message.version))
4249            })
4250            .await?;
4251        message
4252            .lens_actions
4253            .into_iter()
4254            .map(LspStore::deserialize_code_action)
4255            .collect::<Result<Vec<_>>>()
4256            .context("deserializing proto code lens response")
4257    }
4258
4259    fn buffer_id_from_proto(message: &proto::GetCodeLens) -> Result<BufferId> {
4260        BufferId::new(message.buffer_id)
4261    }
4262}
4263
4264impl LinkedEditingRange {
4265    pub fn check_server_capabilities(capabilities: ServerCapabilities) -> bool {
4266        let Some(linked_editing_options) = capabilities.linked_editing_range_provider else {
4267            return false;
4268        };
4269        if let LinkedEditingRangeServerCapabilities::Simple(false) = linked_editing_options {
4270            return false;
4271        }
4272        true
4273    }
4274}
4275
4276#[async_trait(?Send)]
4277impl LspCommand for LinkedEditingRange {
4278    type Response = Vec<Range<Anchor>>;
4279    type LspRequest = lsp::request::LinkedEditingRange;
4280    type ProtoRequest = proto::LinkedEditingRange;
4281
4282    fn display_name(&self) -> &str {
4283        "Linked editing range"
4284    }
4285
4286    fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
4287        Self::check_server_capabilities(capabilities.server_capabilities)
4288    }
4289
4290    fn to_lsp(
4291        &self,
4292        path: &Path,
4293        buffer: &Buffer,
4294        _server: &Arc<LanguageServer>,
4295        _: &App,
4296    ) -> Result<lsp::LinkedEditingRangeParams> {
4297        let position = self.position.to_point_utf16(&buffer.snapshot());
4298        Ok(lsp::LinkedEditingRangeParams {
4299            text_document_position_params: make_lsp_text_document_position(path, position)?,
4300            work_done_progress_params: Default::default(),
4301        })
4302    }
4303
4304    async fn response_from_lsp(
4305        self,
4306        message: Option<lsp::LinkedEditingRanges>,
4307        _: Entity<LspStore>,
4308        buffer: Entity<Buffer>,
4309        _server_id: LanguageServerId,
4310        cx: AsyncApp,
4311    ) -> Result<Vec<Range<Anchor>>> {
4312        if let Some(lsp::LinkedEditingRanges { mut ranges, .. }) = message {
4313            ranges.sort_by_key(|range| range.start);
4314
4315            Ok(buffer.read_with(&cx, |buffer, _| {
4316                ranges
4317                    .into_iter()
4318                    .map(|range| {
4319                        let start =
4320                            buffer.clip_point_utf16(point_from_lsp(range.start), Bias::Left);
4321                        let end = buffer.clip_point_utf16(point_from_lsp(range.end), Bias::Left);
4322                        buffer.anchor_before(start)..buffer.anchor_after(end)
4323                    })
4324                    .collect()
4325            }))
4326        } else {
4327            Ok(vec![])
4328        }
4329    }
4330
4331    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::LinkedEditingRange {
4332        proto::LinkedEditingRange {
4333            project_id,
4334            buffer_id: buffer.remote_id().to_proto(),
4335            position: Some(serialize_anchor(&self.position)),
4336            version: serialize_version(&buffer.version()),
4337        }
4338    }
4339
4340    async fn from_proto(
4341        message: proto::LinkedEditingRange,
4342        _: Entity<LspStore>,
4343        buffer: Entity<Buffer>,
4344        mut cx: AsyncApp,
4345    ) -> Result<Self> {
4346        let position = message.position.context("invalid position")?;
4347        buffer
4348            .update(&mut cx, |buffer, _| {
4349                buffer.wait_for_version(deserialize_version(&message.version))
4350            })
4351            .await?;
4352        let position = deserialize_anchor(position).context("invalid position")?;
4353        buffer
4354            .update(&mut cx, |buffer, _| buffer.wait_for_anchors([position]))
4355            .await?;
4356        Ok(Self { position })
4357    }
4358
4359    fn response_to_proto(
4360        response: Vec<Range<Anchor>>,
4361        _: &mut LspStore,
4362        _: PeerId,
4363        buffer_version: &clock::Global,
4364        _: &mut App,
4365    ) -> proto::LinkedEditingRangeResponse {
4366        proto::LinkedEditingRangeResponse {
4367            items: response
4368                .into_iter()
4369                .map(|range| proto::AnchorRange {
4370                    start: Some(serialize_anchor(&range.start)),
4371                    end: Some(serialize_anchor(&range.end)),
4372                })
4373                .collect(),
4374            version: serialize_version(buffer_version),
4375        }
4376    }
4377
4378    async fn response_from_proto(
4379        self,
4380        message: proto::LinkedEditingRangeResponse,
4381        _: Entity<LspStore>,
4382        buffer: Entity<Buffer>,
4383        mut cx: AsyncApp,
4384    ) -> Result<Vec<Range<Anchor>>> {
4385        buffer
4386            .update(&mut cx, |buffer, _| {
4387                buffer.wait_for_version(deserialize_version(&message.version))
4388            })
4389            .await?;
4390        let items: Vec<Range<Anchor>> = message
4391            .items
4392            .into_iter()
4393            .filter_map(|range| {
4394                let start = deserialize_anchor(range.start?)?;
4395                let end = deserialize_anchor(range.end?)?;
4396                Some(start..end)
4397            })
4398            .collect();
4399        for range in &items {
4400            buffer
4401                .update(&mut cx, |buffer, _| {
4402                    buffer.wait_for_anchors([range.start, range.end])
4403                })
4404                .await?;
4405        }
4406        Ok(items)
4407    }
4408
4409    fn buffer_id_from_proto(message: &proto::LinkedEditingRange) -> Result<BufferId> {
4410        BufferId::new(message.buffer_id)
4411    }
4412}
4413
4414impl GetDocumentDiagnostics {
4415    pub fn diagnostics_from_proto(
4416        response: proto::GetDocumentDiagnosticsResponse,
4417    ) -> Vec<LspPullDiagnostics> {
4418        response
4419            .pulled_diagnostics
4420            .into_iter()
4421            .filter_map(|diagnostics| {
4422                Some(LspPullDiagnostics::Response {
4423                    registration_id: diagnostics.registration_id.map(SharedString::from),
4424                    server_id: LanguageServerId::from_proto(diagnostics.server_id),
4425                    uri: lsp::Uri::from_str(diagnostics.uri.as_str()).log_err()?,
4426                    diagnostics: if diagnostics.changed {
4427                        PulledDiagnostics::Unchanged {
4428                            result_id: SharedString::new(diagnostics.result_id?),
4429                        }
4430                    } else {
4431                        PulledDiagnostics::Changed {
4432                            result_id: diagnostics.result_id.map(SharedString::new),
4433                            diagnostics: diagnostics
4434                                .diagnostics
4435                                .into_iter()
4436                                .filter_map(|diagnostic| {
4437                                    GetDocumentDiagnostics::deserialize_lsp_diagnostic(diagnostic)
4438                                        .context("deserializing diagnostics")
4439                                        .log_err()
4440                                })
4441                                .collect(),
4442                        }
4443                    },
4444                })
4445            })
4446            .collect()
4447    }
4448
4449    pub fn deserialize_lsp_diagnostic(diagnostic: proto::LspDiagnostic) -> Result<lsp::Diagnostic> {
4450        let start = diagnostic.start.context("invalid start range")?;
4451        let end = diagnostic.end.context("invalid end range")?;
4452
4453        let range = Range::<PointUtf16> {
4454            start: PointUtf16 {
4455                row: start.row,
4456                column: start.column,
4457            },
4458            end: PointUtf16 {
4459                row: end.row,
4460                column: end.column,
4461            },
4462        };
4463
4464        let data = diagnostic.data.and_then(|data| Value::from_str(&data).ok());
4465        let code = diagnostic.code.map(lsp::NumberOrString::String);
4466
4467        let related_information = diagnostic
4468            .related_information
4469            .into_iter()
4470            .map(|info| {
4471                let start = info.location_range_start.unwrap();
4472                let end = info.location_range_end.unwrap();
4473
4474                lsp::DiagnosticRelatedInformation {
4475                    location: lsp::Location {
4476                        range: lsp::Range {
4477                            start: point_to_lsp(PointUtf16::new(start.row, start.column)),
4478                            end: point_to_lsp(PointUtf16::new(end.row, end.column)),
4479                        },
4480                        uri: lsp::Uri::from_str(&info.location_url.unwrap()).unwrap(),
4481                    },
4482                    message: info.message,
4483                }
4484            })
4485            .collect::<Vec<_>>();
4486
4487        let tags = diagnostic
4488            .tags
4489            .into_iter()
4490            .filter_map(|tag| match proto::LspDiagnosticTag::from_i32(tag) {
4491                Some(proto::LspDiagnosticTag::Unnecessary) => Some(lsp::DiagnosticTag::UNNECESSARY),
4492                Some(proto::LspDiagnosticTag::Deprecated) => Some(lsp::DiagnosticTag::DEPRECATED),
4493                _ => None,
4494            })
4495            .collect::<Vec<_>>();
4496
4497        Ok(lsp::Diagnostic {
4498            range: language::range_to_lsp(range)?,
4499            severity: match proto::lsp_diagnostic::Severity::from_i32(diagnostic.severity).unwrap()
4500            {
4501                proto::lsp_diagnostic::Severity::Error => Some(lsp::DiagnosticSeverity::ERROR),
4502                proto::lsp_diagnostic::Severity::Warning => Some(lsp::DiagnosticSeverity::WARNING),
4503                proto::lsp_diagnostic::Severity::Information => {
4504                    Some(lsp::DiagnosticSeverity::INFORMATION)
4505                }
4506                proto::lsp_diagnostic::Severity::Hint => Some(lsp::DiagnosticSeverity::HINT),
4507                _ => None,
4508            },
4509            code,
4510            code_description: diagnostic
4511                .code_description
4512                .map(|code_description| CodeDescription {
4513                    href: Some(lsp::Uri::from_str(&code_description).unwrap()),
4514                }),
4515            related_information: Some(related_information),
4516            tags: Some(tags),
4517            source: diagnostic.source.clone(),
4518            message: diagnostic.message,
4519            data,
4520        })
4521    }
4522
4523    pub fn serialize_lsp_diagnostic(diagnostic: lsp::Diagnostic) -> Result<proto::LspDiagnostic> {
4524        let range = language::range_from_lsp(diagnostic.range);
4525        let related_information = diagnostic
4526            .related_information
4527            .unwrap_or_default()
4528            .into_iter()
4529            .map(|related_information| {
4530                let location_range_start =
4531                    point_from_lsp(related_information.location.range.start).0;
4532                let location_range_end = point_from_lsp(related_information.location.range.end).0;
4533
4534                Ok(proto::LspDiagnosticRelatedInformation {
4535                    location_url: Some(related_information.location.uri.to_string()),
4536                    location_range_start: Some(proto::PointUtf16 {
4537                        row: location_range_start.row,
4538                        column: location_range_start.column,
4539                    }),
4540                    location_range_end: Some(proto::PointUtf16 {
4541                        row: location_range_end.row,
4542                        column: location_range_end.column,
4543                    }),
4544                    message: related_information.message,
4545                })
4546            })
4547            .collect::<Result<Vec<_>>>()?;
4548
4549        let tags = diagnostic
4550            .tags
4551            .unwrap_or_default()
4552            .into_iter()
4553            .map(|tag| match tag {
4554                lsp::DiagnosticTag::UNNECESSARY => proto::LspDiagnosticTag::Unnecessary,
4555                lsp::DiagnosticTag::DEPRECATED => proto::LspDiagnosticTag::Deprecated,
4556                _ => proto::LspDiagnosticTag::None,
4557            } as i32)
4558            .collect();
4559
4560        Ok(proto::LspDiagnostic {
4561            start: Some(proto::PointUtf16 {
4562                row: range.start.0.row,
4563                column: range.start.0.column,
4564            }),
4565            end: Some(proto::PointUtf16 {
4566                row: range.end.0.row,
4567                column: range.end.0.column,
4568            }),
4569            severity: match diagnostic.severity {
4570                Some(lsp::DiagnosticSeverity::ERROR) => proto::lsp_diagnostic::Severity::Error,
4571                Some(lsp::DiagnosticSeverity::WARNING) => proto::lsp_diagnostic::Severity::Warning,
4572                Some(lsp::DiagnosticSeverity::INFORMATION) => {
4573                    proto::lsp_diagnostic::Severity::Information
4574                }
4575                Some(lsp::DiagnosticSeverity::HINT) => proto::lsp_diagnostic::Severity::Hint,
4576                _ => proto::lsp_diagnostic::Severity::None,
4577            } as i32,
4578            code: diagnostic.code.as_ref().map(|code| match code {
4579                lsp::NumberOrString::Number(code) => code.to_string(),
4580                lsp::NumberOrString::String(code) => code.clone(),
4581            }),
4582            source: diagnostic.source.clone(),
4583            related_information,
4584            tags,
4585            code_description: diagnostic
4586                .code_description
4587                .and_then(|desc| desc.href.map(|url| url.to_string())),
4588            message: diagnostic.message,
4589            data: diagnostic.data.as_ref().map(|data| data.to_string()),
4590        })
4591    }
4592
4593    pub fn deserialize_workspace_diagnostics_report(
4594        report: lsp::WorkspaceDiagnosticReportResult,
4595        server_id: LanguageServerId,
4596        registration_id: Option<SharedString>,
4597    ) -> Vec<WorkspaceLspPullDiagnostics> {
4598        let mut pulled_diagnostics = HashMap::default();
4599        match report {
4600            lsp::WorkspaceDiagnosticReportResult::Report(workspace_diagnostic_report) => {
4601                for report in workspace_diagnostic_report.items {
4602                    match report {
4603                        lsp::WorkspaceDocumentDiagnosticReport::Full(report) => {
4604                            process_full_workspace_diagnostics_report(
4605                                &mut pulled_diagnostics,
4606                                server_id,
4607                                report,
4608                                registration_id.clone(),
4609                            )
4610                        }
4611                        lsp::WorkspaceDocumentDiagnosticReport::Unchanged(report) => {
4612                            process_unchanged_workspace_diagnostics_report(
4613                                &mut pulled_diagnostics,
4614                                server_id,
4615                                report,
4616                                registration_id.clone(),
4617                            )
4618                        }
4619                    }
4620                }
4621            }
4622            lsp::WorkspaceDiagnosticReportResult::Partial(
4623                workspace_diagnostic_report_partial_result,
4624            ) => {
4625                for report in workspace_diagnostic_report_partial_result.items {
4626                    match report {
4627                        lsp::WorkspaceDocumentDiagnosticReport::Full(report) => {
4628                            process_full_workspace_diagnostics_report(
4629                                &mut pulled_diagnostics,
4630                                server_id,
4631                                report,
4632                                registration_id.clone(),
4633                            )
4634                        }
4635                        lsp::WorkspaceDocumentDiagnosticReport::Unchanged(report) => {
4636                            process_unchanged_workspace_diagnostics_report(
4637                                &mut pulled_diagnostics,
4638                                server_id,
4639                                report,
4640                                registration_id.clone(),
4641                            )
4642                        }
4643                    }
4644                }
4645            }
4646        }
4647        pulled_diagnostics.into_values().collect()
4648    }
4649}
4650
4651#[derive(Debug)]
4652pub struct WorkspaceLspPullDiagnostics {
4653    pub version: Option<i32>,
4654    pub diagnostics: LspPullDiagnostics,
4655}
4656
4657fn process_full_workspace_diagnostics_report(
4658    diagnostics: &mut HashMap<lsp::Uri, WorkspaceLspPullDiagnostics>,
4659    server_id: LanguageServerId,
4660    report: lsp::WorkspaceFullDocumentDiagnosticReport,
4661    registration_id: Option<SharedString>,
4662) {
4663    let mut new_diagnostics = HashMap::default();
4664    process_full_diagnostics_report(
4665        &mut new_diagnostics,
4666        server_id,
4667        report.uri,
4668        report.full_document_diagnostic_report,
4669        registration_id,
4670    );
4671    diagnostics.extend(new_diagnostics.into_iter().map(|(uri, diagnostics)| {
4672        (
4673            uri,
4674            WorkspaceLspPullDiagnostics {
4675                version: report.version.map(|v| v as i32),
4676                diagnostics,
4677            },
4678        )
4679    }));
4680}
4681
4682fn process_unchanged_workspace_diagnostics_report(
4683    diagnostics: &mut HashMap<lsp::Uri, WorkspaceLspPullDiagnostics>,
4684    server_id: LanguageServerId,
4685    report: lsp::WorkspaceUnchangedDocumentDiagnosticReport,
4686    registration_id: Option<SharedString>,
4687) {
4688    let mut new_diagnostics = HashMap::default();
4689    process_unchanged_diagnostics_report(
4690        &mut new_diagnostics,
4691        server_id,
4692        report.uri,
4693        report.unchanged_document_diagnostic_report,
4694        registration_id,
4695    );
4696    diagnostics.extend(new_diagnostics.into_iter().map(|(uri, diagnostics)| {
4697        (
4698            uri,
4699            WorkspaceLspPullDiagnostics {
4700                version: report.version.map(|v| v as i32),
4701                diagnostics,
4702            },
4703        )
4704    }));
4705}
4706
4707#[async_trait(?Send)]
4708impl LspCommand for GetDocumentDiagnostics {
4709    type Response = Vec<LspPullDiagnostics>;
4710    type LspRequest = lsp::request::DocumentDiagnosticRequest;
4711    type ProtoRequest = proto::GetDocumentDiagnostics;
4712
4713    fn display_name(&self) -> &str {
4714        "Get diagnostics"
4715    }
4716
4717    fn check_capabilities(&self, _: AdapterServerCapabilities) -> bool {
4718        true
4719    }
4720
4721    fn to_lsp(
4722        &self,
4723        path: &Path,
4724        _: &Buffer,
4725        _: &Arc<LanguageServer>,
4726        _: &App,
4727    ) -> Result<lsp::DocumentDiagnosticParams> {
4728        Ok(lsp::DocumentDiagnosticParams {
4729            text_document: lsp::TextDocumentIdentifier {
4730                uri: file_path_to_lsp_url(path)?,
4731            },
4732            identifier: self.identifier.as_ref().map(ToString::to_string),
4733            previous_result_id: self.previous_result_id.as_ref().map(ToString::to_string),
4734            partial_result_params: Default::default(),
4735            work_done_progress_params: Default::default(),
4736        })
4737    }
4738
4739    async fn response_from_lsp(
4740        self,
4741        message: lsp::DocumentDiagnosticReportResult,
4742        _: Entity<LspStore>,
4743        buffer: Entity<Buffer>,
4744        server_id: LanguageServerId,
4745        cx: AsyncApp,
4746    ) -> Result<Self::Response> {
4747        let url = buffer.read_with(&cx, |buffer, cx| {
4748            buffer
4749                .file()
4750                .and_then(|file| file.as_local())
4751                .map(|file| {
4752                    let abs_path = file.abs_path(cx);
4753                    file_path_to_lsp_url(&abs_path)
4754                })
4755                .transpose()?
4756                .with_context(|| format!("missing url on buffer {}", buffer.remote_id()))
4757        })?;
4758
4759        let mut pulled_diagnostics = HashMap::default();
4760        match message {
4761            lsp::DocumentDiagnosticReportResult::Report(report) => match report {
4762                lsp::DocumentDiagnosticReport::Full(report) => {
4763                    if let Some(related_documents) = report.related_documents {
4764                        process_related_documents(
4765                            &mut pulled_diagnostics,
4766                            server_id,
4767                            related_documents,
4768                            self.registration_id.clone(),
4769                        );
4770                    }
4771                    process_full_diagnostics_report(
4772                        &mut pulled_diagnostics,
4773                        server_id,
4774                        url,
4775                        report.full_document_diagnostic_report,
4776                        self.registration_id,
4777                    );
4778                }
4779                lsp::DocumentDiagnosticReport::Unchanged(report) => {
4780                    if let Some(related_documents) = report.related_documents {
4781                        process_related_documents(
4782                            &mut pulled_diagnostics,
4783                            server_id,
4784                            related_documents,
4785                            self.registration_id.clone(),
4786                        );
4787                    }
4788                    process_unchanged_diagnostics_report(
4789                        &mut pulled_diagnostics,
4790                        server_id,
4791                        url,
4792                        report.unchanged_document_diagnostic_report,
4793                        self.registration_id,
4794                    );
4795                }
4796            },
4797            lsp::DocumentDiagnosticReportResult::Partial(report) => {
4798                if let Some(related_documents) = report.related_documents {
4799                    process_related_documents(
4800                        &mut pulled_diagnostics,
4801                        server_id,
4802                        related_documents,
4803                        self.registration_id,
4804                    );
4805                }
4806            }
4807        }
4808
4809        Ok(pulled_diagnostics.into_values().collect())
4810    }
4811
4812    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetDocumentDiagnostics {
4813        proto::GetDocumentDiagnostics {
4814            project_id,
4815            buffer_id: buffer.remote_id().into(),
4816            version: serialize_version(&buffer.version()),
4817        }
4818    }
4819
4820    async fn from_proto(
4821        _: proto::GetDocumentDiagnostics,
4822        _: Entity<LspStore>,
4823        _: Entity<Buffer>,
4824        _: AsyncApp,
4825    ) -> Result<Self> {
4826        anyhow::bail!(
4827            "proto::GetDocumentDiagnostics is not expected to be converted from proto directly, as it needs `previous_result_id` fetched first"
4828        )
4829    }
4830
4831    fn response_to_proto(
4832        response: Self::Response,
4833        _: &mut LspStore,
4834        _: PeerId,
4835        _: &clock::Global,
4836        _: &mut App,
4837    ) -> proto::GetDocumentDiagnosticsResponse {
4838        let pulled_diagnostics = response
4839            .into_iter()
4840            .filter_map(|diagnostics| match diagnostics {
4841                LspPullDiagnostics::Default => None,
4842                LspPullDiagnostics::Response {
4843                    server_id,
4844                    uri,
4845                    diagnostics,
4846                    registration_id,
4847                } => {
4848                    let mut changed = false;
4849                    let (diagnostics, result_id) = match diagnostics {
4850                        PulledDiagnostics::Unchanged { result_id } => (Vec::new(), Some(result_id)),
4851                        PulledDiagnostics::Changed {
4852                            result_id,
4853                            diagnostics,
4854                        } => {
4855                            changed = true;
4856                            (diagnostics, result_id)
4857                        }
4858                    };
4859                    Some(proto::PulledDiagnostics {
4860                        changed,
4861                        result_id: result_id.map(|id| id.to_string()),
4862                        uri: uri.to_string(),
4863                        server_id: server_id.to_proto(),
4864                        diagnostics: diagnostics
4865                            .into_iter()
4866                            .filter_map(|diagnostic| {
4867                                GetDocumentDiagnostics::serialize_lsp_diagnostic(diagnostic)
4868                                    .context("serializing diagnostics")
4869                                    .log_err()
4870                            })
4871                            .collect(),
4872                        registration_id: registration_id.as_ref().map(ToString::to_string),
4873                    })
4874                }
4875            })
4876            .collect();
4877
4878        proto::GetDocumentDiagnosticsResponse { pulled_diagnostics }
4879    }
4880
4881    async fn response_from_proto(
4882        self,
4883        response: proto::GetDocumentDiagnosticsResponse,
4884        _: Entity<LspStore>,
4885        _: Entity<Buffer>,
4886        _: AsyncApp,
4887    ) -> Result<Self::Response> {
4888        Ok(Self::diagnostics_from_proto(response))
4889    }
4890
4891    fn buffer_id_from_proto(message: &proto::GetDocumentDiagnostics) -> Result<BufferId> {
4892        BufferId::new(message.buffer_id)
4893    }
4894}
4895
4896#[async_trait(?Send)]
4897impl LspCommand for GetDocumentColor {
4898    type Response = Vec<DocumentColor>;
4899    type LspRequest = lsp::request::DocumentColor;
4900    type ProtoRequest = proto::GetDocumentColor;
4901
4902    fn display_name(&self) -> &str {
4903        "Document color"
4904    }
4905
4906    fn check_capabilities(&self, server_capabilities: AdapterServerCapabilities) -> bool {
4907        server_capabilities
4908            .server_capabilities
4909            .color_provider
4910            .as_ref()
4911            .is_some_and(|capability| match capability {
4912                lsp::ColorProviderCapability::Simple(supported) => *supported,
4913                lsp::ColorProviderCapability::ColorProvider(..) => true,
4914                lsp::ColorProviderCapability::Options(..) => true,
4915            })
4916    }
4917
4918    fn to_lsp(
4919        &self,
4920        path: &Path,
4921        _: &Buffer,
4922        _: &Arc<LanguageServer>,
4923        _: &App,
4924    ) -> Result<lsp::DocumentColorParams> {
4925        Ok(lsp::DocumentColorParams {
4926            text_document: make_text_document_identifier(path)?,
4927            work_done_progress_params: Default::default(),
4928            partial_result_params: Default::default(),
4929        })
4930    }
4931
4932    async fn response_from_lsp(
4933        self,
4934        message: Vec<lsp::ColorInformation>,
4935        _: Entity<LspStore>,
4936        _: Entity<Buffer>,
4937        _: LanguageServerId,
4938        _: AsyncApp,
4939    ) -> Result<Self::Response> {
4940        Ok(message
4941            .into_iter()
4942            .map(|color| DocumentColor {
4943                lsp_range: color.range,
4944                color: color.color,
4945                resolved: false,
4946                color_presentations: Vec::new(),
4947            })
4948            .collect())
4949    }
4950
4951    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest {
4952        proto::GetDocumentColor {
4953            project_id,
4954            buffer_id: buffer.remote_id().to_proto(),
4955            version: serialize_version(&buffer.version()),
4956        }
4957    }
4958
4959    async fn from_proto(
4960        _: Self::ProtoRequest,
4961        _: Entity<LspStore>,
4962        _: Entity<Buffer>,
4963        _: AsyncApp,
4964    ) -> Result<Self> {
4965        Ok(Self {})
4966    }
4967
4968    fn response_to_proto(
4969        response: Self::Response,
4970        _: &mut LspStore,
4971        _: PeerId,
4972        buffer_version: &clock::Global,
4973        _: &mut App,
4974    ) -> proto::GetDocumentColorResponse {
4975        proto::GetDocumentColorResponse {
4976            colors: response
4977                .into_iter()
4978                .map(|color| {
4979                    let start = point_from_lsp(color.lsp_range.start).0;
4980                    let end = point_from_lsp(color.lsp_range.end).0;
4981                    proto::ColorInformation {
4982                        red: color.color.red,
4983                        green: color.color.green,
4984                        blue: color.color.blue,
4985                        alpha: color.color.alpha,
4986                        lsp_range_start: Some(proto::PointUtf16 {
4987                            row: start.row,
4988                            column: start.column,
4989                        }),
4990                        lsp_range_end: Some(proto::PointUtf16 {
4991                            row: end.row,
4992                            column: end.column,
4993                        }),
4994                    }
4995                })
4996                .collect(),
4997            version: serialize_version(buffer_version),
4998        }
4999    }
5000
5001    async fn response_from_proto(
5002        self,
5003        message: proto::GetDocumentColorResponse,
5004        _: Entity<LspStore>,
5005        _: Entity<Buffer>,
5006        _: AsyncApp,
5007    ) -> Result<Self::Response> {
5008        Ok(message
5009            .colors
5010            .into_iter()
5011            .filter_map(|color| {
5012                let start = color.lsp_range_start?;
5013                let start = PointUtf16::new(start.row, start.column);
5014                let end = color.lsp_range_end?;
5015                let end = PointUtf16::new(end.row, end.column);
5016                Some(DocumentColor {
5017                    resolved: false,
5018                    color_presentations: Vec::new(),
5019                    lsp_range: lsp::Range {
5020                        start: point_to_lsp(start),
5021                        end: point_to_lsp(end),
5022                    },
5023                    color: lsp::Color {
5024                        red: color.red,
5025                        green: color.green,
5026                        blue: color.blue,
5027                        alpha: color.alpha,
5028                    },
5029                })
5030            })
5031            .collect())
5032    }
5033
5034    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId> {
5035        BufferId::new(message.buffer_id)
5036    }
5037}
5038
5039#[async_trait(?Send)]
5040impl LspCommand for GetFoldingRanges {
5041    type Response = Vec<LspFoldingRange>;
5042    type LspRequest = lsp::request::FoldingRangeRequest;
5043    type ProtoRequest = proto::GetFoldingRanges;
5044
5045    fn display_name(&self) -> &str {
5046        "Folding ranges"
5047    }
5048
5049    fn check_capabilities(&self, server_capabilities: AdapterServerCapabilities) -> bool {
5050        server_capabilities
5051            .server_capabilities
5052            .folding_range_provider
5053            .as_ref()
5054            .is_some_and(|capability| match capability {
5055                lsp::FoldingRangeProviderCapability::Simple(supported) => *supported,
5056                lsp::FoldingRangeProviderCapability::FoldingProvider(..)
5057                | lsp::FoldingRangeProviderCapability::Options(..) => true,
5058            })
5059    }
5060
5061    fn to_lsp(
5062        &self,
5063        path: &Path,
5064        _: &Buffer,
5065        _: &Arc<LanguageServer>,
5066        _: &App,
5067    ) -> Result<lsp::FoldingRangeParams> {
5068        Ok(lsp::FoldingRangeParams {
5069            text_document: make_text_document_identifier(path)?,
5070            work_done_progress_params: Default::default(),
5071            partial_result_params: Default::default(),
5072        })
5073    }
5074
5075    async fn response_from_lsp(
5076        self,
5077        message: Option<Vec<lsp::FoldingRange>>,
5078        _: Entity<LspStore>,
5079        buffer: Entity<Buffer>,
5080        _: LanguageServerId,
5081        cx: AsyncApp,
5082    ) -> Result<Self::Response> {
5083        let snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot());
5084        let max_point = snapshot.max_point_utf16();
5085        Ok(message
5086            .unwrap_or_default()
5087            .into_iter()
5088            .filter(|range| range.start_line < range.end_line)
5089            .filter(|range| range.start_line <= max_point.row && range.end_line <= max_point.row)
5090            .map(|folding_range| {
5091                let start_col = folding_range.start_character.unwrap_or(u32::MAX);
5092                let end_col = folding_range.end_character.unwrap_or(u32::MAX);
5093                let start = snapshot.clip_point_utf16(
5094                    Unclipped(PointUtf16::new(folding_range.start_line, start_col)),
5095                    Bias::Right,
5096                );
5097                let end = snapshot.clip_point_utf16(
5098                    Unclipped(PointUtf16::new(folding_range.end_line, end_col)),
5099                    Bias::Left,
5100                );
5101                let start = snapshot.anchor_after(start);
5102                let end = snapshot.anchor_before(end);
5103                let collapsed_text = folding_range
5104                    .collapsed_text
5105                    .filter(|t| !t.is_empty())
5106                    .map(|t| SharedString::from(crate::lsp_store::collapse_newlines(&t, " ")));
5107                LspFoldingRange {
5108                    range: start..end,
5109                    collapsed_text,
5110                }
5111            })
5112            .collect())
5113    }
5114
5115    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest {
5116        proto::GetFoldingRanges {
5117            project_id,
5118            buffer_id: buffer.remote_id().to_proto(),
5119            version: serialize_version(&buffer.version()),
5120        }
5121    }
5122
5123    async fn from_proto(
5124        _: Self::ProtoRequest,
5125        _: Entity<LspStore>,
5126        _: Entity<Buffer>,
5127        _: AsyncApp,
5128    ) -> Result<Self> {
5129        Ok(Self)
5130    }
5131
5132    fn response_to_proto(
5133        response: Self::Response,
5134        _: &mut LspStore,
5135        _: PeerId,
5136        buffer_version: &clock::Global,
5137        _: &mut App,
5138    ) -> proto::GetFoldingRangesResponse {
5139        let mut ranges = Vec::with_capacity(response.len());
5140        let mut collapsed_texts = Vec::with_capacity(response.len());
5141        for folding_range in response {
5142            ranges.push(serialize_anchor_range(folding_range.range));
5143            collapsed_texts.push(
5144                folding_range
5145                    .collapsed_text
5146                    .map(|t| t.to_string())
5147                    .unwrap_or_default(),
5148            );
5149        }
5150        proto::GetFoldingRangesResponse {
5151            ranges,
5152            collapsed_texts,
5153            version: serialize_version(buffer_version),
5154        }
5155    }
5156
5157    async fn response_from_proto(
5158        self,
5159        message: proto::GetFoldingRangesResponse,
5160        _: Entity<LspStore>,
5161        buffer: Entity<Buffer>,
5162        mut cx: AsyncApp,
5163    ) -> Result<Self::Response> {
5164        buffer
5165            .update(&mut cx, |buffer, _| {
5166                buffer.wait_for_version(deserialize_version(&message.version))
5167            })
5168            .await?;
5169        message
5170            .ranges
5171            .into_iter()
5172            .zip(
5173                message
5174                    .collapsed_texts
5175                    .into_iter()
5176                    .map(Some)
5177                    .chain(std::iter::repeat(None)),
5178            )
5179            .map(|(range, collapsed_text)| {
5180                Ok(LspFoldingRange {
5181                    range: deserialize_anchor_range(range)?,
5182                    collapsed_text: collapsed_text
5183                        .filter(|t| !t.is_empty())
5184                        .map(SharedString::from),
5185                })
5186            })
5187            .collect()
5188    }
5189
5190    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId> {
5191        BufferId::new(message.buffer_id)
5192    }
5193}
5194
5195#[async_trait(?Send)]
5196impl LspCommand for GetDocumentLinks {
5197    type Response = Vec<LspDocumentLink>;
5198    type LspRequest = lsp::request::DocumentLinkRequest;
5199    type ProtoRequest = proto::GetDocumentLinks;
5200
5201    fn display_name(&self) -> &str {
5202        "Document links"
5203    }
5204
5205    fn check_capabilities(&self, server_capabilities: AdapterServerCapabilities) -> bool {
5206        server_capabilities
5207            .server_capabilities
5208            .document_link_provider
5209            .is_some()
5210    }
5211
5212    fn to_lsp(
5213        &self,
5214        path: &Path,
5215        _: &Buffer,
5216        _: &Arc<LanguageServer>,
5217        _: &App,
5218    ) -> Result<lsp::DocumentLinkParams> {
5219        Ok(lsp::DocumentLinkParams {
5220            text_document: make_text_document_identifier(path)?,
5221            work_done_progress_params: lsp::WorkDoneProgressParams::default(),
5222            partial_result_params: lsp::PartialResultParams::default(),
5223        })
5224    }
5225
5226    async fn response_from_lsp(
5227        self,
5228        message: Option<Vec<lsp::DocumentLink>>,
5229        _: Entity<LspStore>,
5230        buffer: Entity<Buffer>,
5231        _: LanguageServerId,
5232        cx: AsyncApp,
5233    ) -> Result<Self::Response> {
5234        let snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot());
5235        Ok(message
5236            .unwrap_or_default()
5237            .into_iter()
5238            .map(|link| {
5239                let start = snapshot.clip_point_utf16(
5240                    Unclipped(PointUtf16::new(
5241                        link.range.start.line,
5242                        link.range.start.character,
5243                    )),
5244                    Bias::Left,
5245                );
5246                let end = snapshot.clip_point_utf16(
5247                    Unclipped(PointUtf16::new(
5248                        link.range.end.line,
5249                        link.range.end.character,
5250                    )),
5251                    Bias::Right,
5252                );
5253                LspDocumentLink {
5254                    range: snapshot.anchor_after(start)..snapshot.anchor_before(end),
5255                    target: link.target.map(|url| url.to_string().into()),
5256                    tooltip: link.tooltip.map(SharedString::from),
5257                    data: link.data,
5258                    resolved: false,
5259                }
5260            })
5261            .collect())
5262    }
5263
5264    fn to_proto(&self, project_id: u64, buffer: &Buffer) -> Self::ProtoRequest {
5265        proto::GetDocumentLinks {
5266            project_id,
5267            buffer_id: buffer.remote_id().to_proto(),
5268            version: serialize_version(&buffer.version()),
5269        }
5270    }
5271
5272    async fn from_proto(
5273        _: Self::ProtoRequest,
5274        _: Entity<LspStore>,
5275        _: Entity<Buffer>,
5276        _: AsyncApp,
5277    ) -> Result<Self> {
5278        Ok(Self)
5279    }
5280
5281    fn response_to_proto(
5282        response: Self::Response,
5283        _: &mut LspStore,
5284        _: PeerId,
5285        buffer_version: &clock::Global,
5286        _: &mut App,
5287    ) -> proto::GetDocumentLinksResponse {
5288        proto::GetDocumentLinksResponse {
5289            links: response
5290                .into_iter()
5291                .map(|link| proto::DocumentLinkProto {
5292                    range: Some(serialize_anchor_range(link.range)),
5293                    target: link.target.map(String::from),
5294                    tooltip: link.tooltip.map(String::from),
5295                    data: link
5296                        .data
5297                        .map(|d| serde_json::to_string(&d).unwrap_or_default()),
5298                })
5299                .collect(),
5300            version: serialize_version(buffer_version),
5301        }
5302    }
5303
5304    async fn response_from_proto(
5305        self,
5306        message: proto::GetDocumentLinksResponse,
5307        _: Entity<LspStore>,
5308        buffer: Entity<Buffer>,
5309        mut cx: AsyncApp,
5310    ) -> Result<Self::Response> {
5311        buffer
5312            .update(&mut cx, |buffer, _| {
5313                buffer.wait_for_version(deserialize_version(&message.version))
5314            })
5315            .await?;
5316        message
5317            .links
5318            .into_iter()
5319            .map(|link| {
5320                Ok(LspDocumentLink {
5321                    range: deserialize_anchor_range(link.range.context("missing range")?)?,
5322                    target: link.target.map(SharedString::from),
5323                    tooltip: link.tooltip.map(SharedString::from),
5324                    data: link.data.and_then(|d| serde_json::from_str(&d).ok()),
5325                    resolved: false,
5326                })
5327            })
5328            .collect()
5329    }
5330
5331    fn buffer_id_from_proto(message: &Self::ProtoRequest) -> Result<BufferId> {
5332        BufferId::new(message.buffer_id)
5333    }
5334}
5335
5336fn process_related_documents(
5337    diagnostics: &mut HashMap<lsp::Uri, LspPullDiagnostics>,
5338    server_id: LanguageServerId,
5339    documents: impl IntoIterator<Item = (lsp::Uri, lsp::DocumentDiagnosticReportKind)>,
5340    registration_id: Option<SharedString>,
5341) {
5342    for (url, report_kind) in documents {
5343        match report_kind {
5344            lsp::DocumentDiagnosticReportKind::Full(report) => process_full_diagnostics_report(
5345                diagnostics,
5346                server_id,
5347                url,
5348                report,
5349                registration_id.clone(),
5350            ),
5351            lsp::DocumentDiagnosticReportKind::Unchanged(report) => {
5352                process_unchanged_diagnostics_report(
5353                    diagnostics,
5354                    server_id,
5355                    url,
5356                    report,
5357                    registration_id.clone(),
5358                )
5359            }
5360        }
5361    }
5362}
5363
5364fn process_unchanged_diagnostics_report(
5365    diagnostics: &mut HashMap<lsp::Uri, LspPullDiagnostics>,
5366    server_id: LanguageServerId,
5367    uri: lsp::Uri,
5368    report: lsp::UnchangedDocumentDiagnosticReport,
5369    registration_id: Option<SharedString>,
5370) {
5371    let result_id = SharedString::new(report.result_id);
5372    match diagnostics.entry(uri.clone()) {
5373        hash_map::Entry::Occupied(mut o) => match o.get_mut() {
5374            LspPullDiagnostics::Default => {
5375                o.insert(LspPullDiagnostics::Response {
5376                    server_id,
5377                    uri,
5378                    diagnostics: PulledDiagnostics::Unchanged { result_id },
5379                    registration_id,
5380                });
5381            }
5382            LspPullDiagnostics::Response {
5383                server_id: existing_server_id,
5384                uri: existing_uri,
5385                diagnostics: existing_diagnostics,
5386                ..
5387            } => {
5388                if server_id != *existing_server_id || &uri != existing_uri {
5389                    debug_panic!(
5390                        "Unexpected state: file {uri} has two different sets of diagnostics reported"
5391                    );
5392                }
5393                match existing_diagnostics {
5394                    PulledDiagnostics::Unchanged { .. } => {
5395                        *existing_diagnostics = PulledDiagnostics::Unchanged { result_id };
5396                    }
5397                    PulledDiagnostics::Changed { .. } => {}
5398                }
5399            }
5400        },
5401        hash_map::Entry::Vacant(v) => {
5402            v.insert(LspPullDiagnostics::Response {
5403                server_id,
5404                uri,
5405                diagnostics: PulledDiagnostics::Unchanged { result_id },
5406                registration_id,
5407            });
5408        }
5409    }
5410}
5411
5412fn process_full_diagnostics_report(
5413    diagnostics: &mut HashMap<lsp::Uri, LspPullDiagnostics>,
5414    server_id: LanguageServerId,
5415    uri: lsp::Uri,
5416    report: lsp::FullDocumentDiagnosticReport,
5417    registration_id: Option<SharedString>,
5418) {
5419    let result_id = report.result_id.map(SharedString::new);
5420    match diagnostics.entry(uri.clone()) {
5421        hash_map::Entry::Occupied(mut o) => match o.get_mut() {
5422            LspPullDiagnostics::Default => {
5423                o.insert(LspPullDiagnostics::Response {
5424                    server_id,
5425                    uri,
5426                    diagnostics: PulledDiagnostics::Changed {
5427                        result_id,
5428                        diagnostics: report.items,
5429                    },
5430                    registration_id,
5431                });
5432            }
5433            LspPullDiagnostics::Response {
5434                server_id: existing_server_id,
5435                uri: existing_uri,
5436                diagnostics: existing_diagnostics,
5437                ..
5438            } => {
5439                if server_id != *existing_server_id || &uri != existing_uri {
5440                    debug_panic!(
5441                        "Unexpected state: file {uri} has two different sets of diagnostics reported"
5442                    );
5443                }
5444                match existing_diagnostics {
5445                    PulledDiagnostics::Unchanged { .. } => {
5446                        *existing_diagnostics = PulledDiagnostics::Changed {
5447                            result_id,
5448                            diagnostics: report.items,
5449                        };
5450                    }
5451                    PulledDiagnostics::Changed {
5452                        result_id: existing_result_id,
5453                        diagnostics: existing_diagnostics,
5454                    } => {
5455                        if result_id.is_some() {
5456                            *existing_result_id = result_id;
5457                        }
5458                        existing_diagnostics.extend(report.items);
5459                    }
5460                }
5461            }
5462        },
5463        hash_map::Entry::Vacant(v) => {
5464            v.insert(LspPullDiagnostics::Response {
5465                server_id,
5466                uri,
5467                diagnostics: PulledDiagnostics::Changed {
5468                    result_id,
5469                    diagnostics: report.items,
5470                },
5471                registration_id,
5472            });
5473        }
5474    }
5475}
5476
Served at tenant.openagents/omega Member data and write actions are omitted.