Unnamed repository; edit this file 'description' to name the repository.
Keep already computed inlay hint properties instead of late resolving them
Lukas Wirth 2025-01-21
parent 1977aa9 · commit f5b86e0
-rw-r--r--crates/ide/src/inlay_hints.rs48
-rw-r--r--crates/ide/src/inlay_hints/chaining.rs4
-rw-r--r--crates/ide/src/inlay_hints/closing_brace.rs4
-rw-r--r--crates/ide/src/lib.rs2
-rw-r--r--crates/rust-analyzer/src/lsp/to_proto.rs133
5 files changed, 99 insertions, 92 deletions
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index 405cbf6078..088a11bcb4 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/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/crates/ide/src/inlay_hints/chaining.rs b/crates/ide/src/inlay_hints/chaining.rs
index 477fb5156b..8471547727 100644
--- a/crates/ide/src/inlay_hints/chaining.rs
+++ b/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/crates/ide/src/inlay_hints/closing_brace.rs b/crates/ide/src/inlay_hints/closing_brace.rs
index 64f1f83d3f..bd36e2c3be 100644
--- a/crates/ide/src/inlay_hints/closing_brace.rs
+++ b/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/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index 346e2862b0..6ec95ccb62 100644
--- a/crates/ide/src/lib.rs
+++ b/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/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs
index 4947576f19..2a7d95d560 100644
--- a/crates/rust-analyzer/src/lsp/to_proto.rs
+++ b/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,