about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2025-01-21 12:32:11 +0100
committerLukas Wirth <lukastw97@gmail.com>2025-01-21 16:16:51 +0100
commit802d9d53869031e1c63dca15684381a50ec6370c (patch)
tree990b131e49cd52186f820aa22d069b239f3356a2
parent284e0cd74945d05515bd2d257ae814be9bba91d5 (diff)
downloadrust-802d9d53869031e1c63dca15684381a50ec6370c.tar.gz
rust-802d9d53869031e1c63dca15684381a50ec6370c.zip
Keep already computed inlay hint properties instead of late resolving them
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs48
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs133
5 files changed, 99 insertions, 92 deletions
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
index 405cbf60784..088a11bcb4c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
@@ -302,21 +302,21 @@ pub struct InlayHintsConfig {
 }
 
 impl InlayHintsConfig {
-    fn lazy_text_edit(&self, finish: impl FnOnce() -> TextEdit) -> Lazy<TextEdit> {
+    fn lazy_text_edit(&self, finish: impl FnOnce() -> TextEdit) -> LazyProperty<TextEdit> {
         if self.fields_to_resolve.resolve_text_edits {
-            Lazy::Lazy
+            LazyProperty::Lazy
         } else {
             let edit = finish();
             never!(edit.is_empty(), "inlay hint produced an empty text edit");
-            Lazy::Computed(edit)
+            LazyProperty::Computed(edit)
         }
     }
 
-    fn lazy_tooltip(&self, finish: impl FnOnce() -> InlayTooltip) -> Lazy<InlayTooltip> {
+    fn lazy_tooltip(&self, finish: impl FnOnce() -> InlayTooltip) -> LazyProperty<InlayTooltip> {
         if self.fields_to_resolve.resolve_hint_tooltip
             && self.fields_to_resolve.resolve_label_tooltip
         {
-            Lazy::Lazy
+            LazyProperty::Lazy
         } else {
             let tooltip = finish();
             never!(
@@ -327,7 +327,7 @@ impl InlayHintsConfig {
                 .is_empty(),
                 "inlay hint produced an empty tooltip"
             );
-            Lazy::Computed(tooltip)
+            LazyProperty::Computed(tooltip)
         }
     }
 
@@ -336,11 +336,11 @@ impl InlayHintsConfig {
     fn lazy_location_opt(
         &self,
         finish: impl FnOnce() -> Option<FileRange>,
-    ) -> Option<Lazy<FileRange>> {
+    ) -> Option<LazyProperty<FileRange>> {
         if self.fields_to_resolve.resolve_label_location {
-            Some(Lazy::Lazy)
+            Some(LazyProperty::Lazy)
         } else {
-            finish().map(Lazy::Computed)
+            finish().map(LazyProperty::Computed)
         }
     }
 }
@@ -455,7 +455,7 @@ pub struct InlayHint {
     /// The actual label to show in the inlay hint.
     pub label: InlayHintLabel,
     /// Text edit to apply when "accepting" this inlay hint.
-    pub text_edit: Option<Lazy<TextEdit>>,
+    pub text_edit: Option<LazyProperty<TextEdit>>,
     /// Range to recompute inlay hints when trying to resolve for this hint. If this is none, the
     /// hint does not support resolving.
     pub resolve_parent: Option<TextRange>,
@@ -463,15 +463,15 @@ pub struct InlayHint {
 
 /// A type signaling that a value is either computed, or is available for computation.
 #[derive(Clone, Debug)]
-pub enum Lazy<T> {
+pub enum LazyProperty<T> {
     Computed(T),
     Lazy,
 }
 
-impl<T> Lazy<T> {
+impl<T> LazyProperty<T> {
     pub fn computed(self) -> Option<T> {
         match self {
-            Lazy::Computed(it) => Some(it),
+            LazyProperty::Computed(it) => Some(it),
             _ => None,
         }
     }
@@ -522,8 +522,8 @@ pub struct InlayHintLabel {
 impl InlayHintLabel {
     pub fn simple(
         s: impl Into<String>,
-        tooltip: Option<Lazy<InlayTooltip>>,
-        linked_location: Option<Lazy<FileRange>>,
+        tooltip: Option<LazyProperty<InlayTooltip>>,
+        linked_location: Option<LazyProperty<FileRange>>,
     ) -> InlayHintLabel {
         InlayHintLabel {
             parts: smallvec![InlayHintLabelPart { text: s.into(), linked_location, tooltip }],
@@ -607,10 +607,10 @@ pub struct InlayHintLabelPart {
     /// refers to (not necessarily the location itself).
     /// When setting this, no tooltip must be set on the containing hint, or VS Code will display
     /// them both.
-    pub linked_location: Option<Lazy<FileRange>>,
+    pub linked_location: Option<LazyProperty<FileRange>>,
     /// The tooltip to show when hovering over the inlay hint, this may invoke other actions like
     /// hover requests to show.
-    pub tooltip: Option<Lazy<InlayTooltip>>,
+    pub tooltip: Option<LazyProperty<InlayTooltip>>,
 }
 
 impl std::hash::Hash for InlayHintLabelPart {
@@ -624,7 +624,9 @@ impl std::hash::Hash for InlayHintLabelPart {
 impl fmt::Debug for InlayHintLabelPart {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
-            Self { text, linked_location: None, tooltip: None | Some(Lazy::Lazy) } => text.fmt(f),
+            Self { text, linked_location: None, tooltip: None | Some(LazyProperty::Lazy) } => {
+                text.fmt(f)
+            }
             Self { text, linked_location, tooltip } => f
                 .debug_struct("InlayHintLabelPart")
                 .field("text", text)
@@ -632,8 +634,10 @@ impl fmt::Debug for InlayHintLabelPart {
                 .field(
                     "tooltip",
                     &tooltip.as_ref().map_or("", |it| match it {
-                        Lazy::Computed(InlayTooltip::String(it) | InlayTooltip::Markdown(it)) => it,
-                        Lazy::Lazy => "",
+                        LazyProperty::Computed(
+                            InlayTooltip::String(it) | InlayTooltip::Markdown(it),
+                        ) => it,
+                        LazyProperty::Lazy => "",
                     }),
                 )
                 .finish(),
@@ -677,7 +681,7 @@ impl InlayHintLabelBuilder<'_> {
         if !text.is_empty() {
             self.result.parts.push(InlayHintLabelPart {
                 text,
-                linked_location: self.location.take().map(Lazy::Computed),
+                linked_location: self.location.take().map(LazyProperty::Computed),
                 tooltip: None,
             });
         }
@@ -797,7 +801,7 @@ fn ty_to_text_edit(
     ty: &hir::Type,
     offset_to_insert: TextSize,
     prefix: impl Into<String>,
-) -> Option<Lazy<TextEdit>> {
+) -> Option<LazyProperty<TextEdit>> {
     // FIXME: Limit the length and bail out on excess somehow?
     let rendered = sema
         .scope(node_for_hint)
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs
index 477fb5156be..8471547727f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs
@@ -83,7 +83,7 @@ mod tests {
         fixture,
         inlay_hints::{
             tests::{check_expect, check_with_config, DISABLED_CONFIG, TEST_CONFIG},
-            Lazy,
+            LazyProperty,
         },
         InlayHintsConfig,
     };
@@ -102,7 +102,7 @@ mod tests {
         let (analysis, file_id) = fixture::file(ra_fixture);
         let mut inlay_hints = analysis.inlay_hints(&config, file_id, None).unwrap();
         inlay_hints.iter_mut().flat_map(|hint| &mut hint.label.parts).for_each(|hint| {
-            if let Some(Lazy::Computed(loc)) = &mut hint.linked_location {
+            if let Some(LazyProperty::Computed(loc)) = &mut hint.linked_location {
                 loc.range = TextRange::empty(TextSize::from(0));
             }
         });
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs
index 64f1f83d3f5..bd36e2c3be6 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs
@@ -12,7 +12,7 @@ use syntax::{
 };
 
 use crate::{
-    inlay_hints::Lazy, InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind,
+    inlay_hints::LazyProperty, InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind,
 };
 
 pub(super) fn hints(
@@ -143,7 +143,7 @@ pub(super) fn hints(
     acc.push(InlayHint {
         range: closing_token.text_range(),
         kind: InlayKind::ClosingBrace,
-        label: InlayHintLabel::simple(label, None, linked_location.map(Lazy::Computed)),
+        label: InlayHintLabel::simple(label, None, linked_location.map(LazyProperty::Computed)),
         text_edit: None,
         position: InlayHintPosition::After,
         pad_left: true,
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index 346e2862b0f..6ec95ccb62a 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -91,7 +91,7 @@ pub use crate::{
     inlay_hints::{
         AdjustmentHints, AdjustmentHintsMode, ClosureReturnTypeHints, DiscriminantHints,
         GenericParameterHints, InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart,
-        InlayHintPosition, InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints,
+        InlayHintPosition, InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints, LazyProperty
     },
     join_lines::JoinLinesConfig,
     markup::Markup,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
index 4947576f197..2a7d95d560d 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
@@ -11,8 +11,8 @@ use ide::{
     Annotation, AnnotationKind, Assist, AssistKind, Cancellable, CompletionFieldsToResolve,
     CompletionItem, CompletionItemKind, CompletionRelevance, Documentation, FileId, FileRange,
     FileSystemEdit, Fold, FoldKind, Highlight, HlMod, HlOperator, HlPunct, HlRange, HlTag, Indel,
-    InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayKind, Markup,
-    NavigationTarget, ReferenceCategory, RenameError, Runnable, Severity, SignatureHelp,
+    InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayKind, LazyProperty,
+    Markup, NavigationTarget, ReferenceCategory, RenameError, Runnable, Severity, SignatureHelp,
     SnippetEdit, SourceChange, StructureNodeKind, SymbolKind, TextEdit, TextRange, TextSize,
 };
 use ide_db::{assists, rust_doc::format_docs, FxHasher};
@@ -549,12 +549,11 @@ pub(crate) fn inlay_hint(
 ) -> Cancellable<lsp_types::InlayHint> {
     let hint_needs_resolve = |hint: &InlayHint| -> Option<TextRange> {
         hint.resolve_parent.filter(|_| {
-            hint.text_edit.is_some()
-                || hint
-                    .label
-                    .parts
-                    .iter()
-                    .any(|part| part.linked_location.is_some() || part.tooltip.is_some())
+            hint.text_edit.as_ref().is_some_and(LazyProperty::is_lazy)
+                || hint.label.parts.iter().any(|part| {
+                    part.linked_location.as_ref().is_some_and(LazyProperty::is_lazy)
+                        || part.tooltip.as_ref().is_some_and(LazyProperty::is_lazy)
+                })
         })
     };
 
@@ -569,22 +568,21 @@ pub(crate) fn inlay_hint(
     });
 
     let mut something_to_resolve = false;
-    let text_edits = if snap
-        .config
-        .visual_studio_code_version()
-        .is_none_or(|version| VersionReq::parse(">=1.86.0").unwrap().matches(version))
-        && resolve_range_and_hash.is_some()
-        && fields_to_resolve.resolve_text_edits
-    {
-        something_to_resolve |= inlay_hint.text_edit.is_some();
-        None
-    } else {
-        inlay_hint
-            .text_edit
-            .take()
-            .and_then(|it| it.computed())
-            .map(|it| text_edit_vec(line_index, it))
-    };
+    let text_edits = inlay_hint
+        .text_edit
+        .take()
+        .and_then(|it| match it {
+            LazyProperty::Computed(it) => Some(it),
+            LazyProperty::Lazy => {
+                something_to_resolve |=
+                    snap.config.visual_studio_code_version().is_none_or(|version| {
+                        VersionReq::parse(">=1.86.0").unwrap().matches(version)
+                    }) && resolve_range_and_hash.is_some()
+                        && fields_to_resolve.resolve_text_edits;
+                None
+            }
+        })
+        .map(|it| text_edit_vec(line_index, it));
     let (label, tooltip) = inlay_hint_label(
         snap,
         fields_to_resolve,
@@ -637,22 +635,23 @@ fn inlay_hint_label(
     let (label, tooltip) = match &*label.parts {
         [InlayHintLabelPart { linked_location: None, .. }] => {
             let InlayHintLabelPart { text, tooltip, .. } = label.parts.pop().unwrap();
-            let hint_tooltip = if needs_resolve && fields_to_resolve.resolve_hint_tooltip {
-                *something_to_resolve |= tooltip.is_some();
-                None
-            } else {
-                match tooltip.and_then(|it| it.computed()) {
-                    Some(ide::InlayTooltip::String(s)) => {
-                        Some(lsp_types::InlayHintTooltip::String(s))
-                    }
-                    Some(ide::InlayTooltip::Markdown(s)) => {
-                        Some(lsp_types::InlayHintTooltip::MarkupContent(lsp_types::MarkupContent {
-                            kind: lsp_types::MarkupKind::Markdown,
-                            value: s,
-                        }))
-                    }
-                    None => None,
+            let tooltip = tooltip.and_then(|it| match it {
+                LazyProperty::Computed(it) => Some(it),
+                LazyProperty::Lazy => {
+                    *something_to_resolve |=
+                        needs_resolve && fields_to_resolve.resolve_hint_tooltip;
+                    None
                 }
+            });
+            let hint_tooltip = match tooltip {
+                Some(ide::InlayTooltip::String(s)) => Some(lsp_types::InlayHintTooltip::String(s)),
+                Some(ide::InlayTooltip::Markdown(s)) => {
+                    Some(lsp_types::InlayHintTooltip::MarkupContent(lsp_types::MarkupContent {
+                        kind: lsp_types::MarkupKind::Markdown,
+                        value: s,
+                    }))
+                }
+                None => None,
             };
             (lsp_types::InlayHintLabel::String(text), hint_tooltip)
         }
@@ -661,34 +660,38 @@ fn inlay_hint_label(
                 .parts
                 .into_iter()
                 .map(|part| {
-                    let tooltip = if needs_resolve && fields_to_resolve.resolve_label_tooltip {
-                        *something_to_resolve |= part.tooltip.is_some();
-                        None
-                    } else {
-                        match part.tooltip.and_then(|it| it.computed()) {
-                            Some(ide::InlayTooltip::String(s)) => {
-                                Some(lsp_types::InlayHintLabelPartTooltip::String(s))
-                            }
-                            Some(ide::InlayTooltip::Markdown(s)) => {
-                                Some(lsp_types::InlayHintLabelPartTooltip::MarkupContent(
-                                    lsp_types::MarkupContent {
-                                        kind: lsp_types::MarkupKind::Markdown,
-                                        value: s,
-                                    },
-                                ))
-                            }
-                            None => None,
+                    let tooltip = part.tooltip.and_then(|it| match it {
+                        LazyProperty::Computed(it) => Some(it),
+                        LazyProperty::Lazy => {
+                            *something_to_resolve |= fields_to_resolve.resolve_label_tooltip;
+                            None
                         }
+                    });
+                    let tooltip = match tooltip {
+                        Some(ide::InlayTooltip::String(s)) => {
+                            Some(lsp_types::InlayHintLabelPartTooltip::String(s))
+                        }
+                        Some(ide::InlayTooltip::Markdown(s)) => {
+                            Some(lsp_types::InlayHintLabelPartTooltip::MarkupContent(
+                                lsp_types::MarkupContent {
+                                    kind: lsp_types::MarkupKind::Markdown,
+                                    value: s,
+                                },
+                            ))
+                        }
+                        None => None,
                     };
-                    let location = if needs_resolve && fields_to_resolve.resolve_label_location {
-                        *something_to_resolve |= part.linked_location.is_some();
-                        None
-                    } else {
-                        part.linked_location
-                            .and_then(|it| it.computed())
-                            .map(|range| location(snap, range))
-                            .transpose()?
-                    };
+                    let location = part
+                        .linked_location
+                        .and_then(|it| match it {
+                            LazyProperty::Computed(it) => Some(it),
+                            LazyProperty::Lazy => {
+                                *something_to_resolve |= fields_to_resolve.resolve_label_location;
+                                None
+                            }
+                        })
+                        .map(|range| location(snap, range))
+                        .transpose()?;
                     Ok(lsp_types::InlayHintLabelPart {
                         value: part.text,
                         tooltip,