mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
Keep already computed inlay hint properties instead of late resolving them
This commit is contained in:
parent
1977aa99b0
commit
f5b86e056b
@ -302,21 +302,21 @@ pub struct InlayHintsConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
if self.fields_to_resolve.resolve_text_edits {
|
||||||
Lazy::Lazy
|
LazyProperty::Lazy
|
||||||
} else {
|
} else {
|
||||||
let edit = finish();
|
let edit = finish();
|
||||||
never!(edit.is_empty(), "inlay hint produced an empty text edit");
|
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
|
if self.fields_to_resolve.resolve_hint_tooltip
|
||||||
&& self.fields_to_resolve.resolve_label_tooltip
|
&& self.fields_to_resolve.resolve_label_tooltip
|
||||||
{
|
{
|
||||||
Lazy::Lazy
|
LazyProperty::Lazy
|
||||||
} else {
|
} else {
|
||||||
let tooltip = finish();
|
let tooltip = finish();
|
||||||
never!(
|
never!(
|
||||||
@ -327,7 +327,7 @@ impl InlayHintsConfig {
|
|||||||
.is_empty(),
|
.is_empty(),
|
||||||
"inlay hint produced an empty tooltip"
|
"inlay hint produced an empty tooltip"
|
||||||
);
|
);
|
||||||
Lazy::Computed(tooltip)
|
LazyProperty::Computed(tooltip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,11 +336,11 @@ impl InlayHintsConfig {
|
|||||||
fn lazy_location_opt(
|
fn lazy_location_opt(
|
||||||
&self,
|
&self,
|
||||||
finish: impl FnOnce() -> Option<FileRange>,
|
finish: impl FnOnce() -> Option<FileRange>,
|
||||||
) -> Option<Lazy<FileRange>> {
|
) -> Option<LazyProperty<FileRange>> {
|
||||||
if self.fields_to_resolve.resolve_label_location {
|
if self.fields_to_resolve.resolve_label_location {
|
||||||
Some(Lazy::Lazy)
|
Some(LazyProperty::Lazy)
|
||||||
} else {
|
} 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.
|
/// The actual label to show in the inlay hint.
|
||||||
pub label: InlayHintLabel,
|
pub label: InlayHintLabel,
|
||||||
/// Text edit to apply when "accepting" this inlay hint.
|
/// 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
|
/// Range to recompute inlay hints when trying to resolve for this hint. If this is none, the
|
||||||
/// hint does not support resolving.
|
/// hint does not support resolving.
|
||||||
pub resolve_parent: Option<TextRange>,
|
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.
|
/// A type signaling that a value is either computed, or is available for computation.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Lazy<T> {
|
pub enum LazyProperty<T> {
|
||||||
Computed(T),
|
Computed(T),
|
||||||
Lazy,
|
Lazy,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Lazy<T> {
|
impl<T> LazyProperty<T> {
|
||||||
pub fn computed(self) -> Option<T> {
|
pub fn computed(self) -> Option<T> {
|
||||||
match self {
|
match self {
|
||||||
Lazy::Computed(it) => Some(it),
|
LazyProperty::Computed(it) => Some(it),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -522,8 +522,8 @@ pub struct InlayHintLabel {
|
|||||||
impl InlayHintLabel {
|
impl InlayHintLabel {
|
||||||
pub fn simple(
|
pub fn simple(
|
||||||
s: impl Into<String>,
|
s: impl Into<String>,
|
||||||
tooltip: Option<Lazy<InlayTooltip>>,
|
tooltip: Option<LazyProperty<InlayTooltip>>,
|
||||||
linked_location: Option<Lazy<FileRange>>,
|
linked_location: Option<LazyProperty<FileRange>>,
|
||||||
) -> InlayHintLabel {
|
) -> InlayHintLabel {
|
||||||
InlayHintLabel {
|
InlayHintLabel {
|
||||||
parts: smallvec![InlayHintLabelPart { text: s.into(), linked_location, tooltip }],
|
parts: smallvec![InlayHintLabelPart { text: s.into(), linked_location, tooltip }],
|
||||||
@ -607,10 +607,10 @@ pub struct InlayHintLabelPart {
|
|||||||
/// refers to (not necessarily the location itself).
|
/// refers to (not necessarily the location itself).
|
||||||
/// When setting this, no tooltip must be set on the containing hint, or VS Code will display
|
/// When setting this, no tooltip must be set on the containing hint, or VS Code will display
|
||||||
/// them both.
|
/// 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
|
/// The tooltip to show when hovering over the inlay hint, this may invoke other actions like
|
||||||
/// hover requests to show.
|
/// hover requests to show.
|
||||||
pub tooltip: Option<Lazy<InlayTooltip>>,
|
pub tooltip: Option<LazyProperty<InlayTooltip>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::hash::Hash for InlayHintLabelPart {
|
impl std::hash::Hash for InlayHintLabelPart {
|
||||||
@ -624,7 +624,9 @@ impl std::hash::Hash for InlayHintLabelPart {
|
|||||||
impl fmt::Debug for InlayHintLabelPart {
|
impl fmt::Debug for InlayHintLabelPart {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
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
|
Self { text, linked_location, tooltip } => f
|
||||||
.debug_struct("InlayHintLabelPart")
|
.debug_struct("InlayHintLabelPart")
|
||||||
.field("text", text)
|
.field("text", text)
|
||||||
@ -632,8 +634,10 @@ impl fmt::Debug for InlayHintLabelPart {
|
|||||||
.field(
|
.field(
|
||||||
"tooltip",
|
"tooltip",
|
||||||
&tooltip.as_ref().map_or("", |it| match it {
|
&tooltip.as_ref().map_or("", |it| match it {
|
||||||
Lazy::Computed(InlayTooltip::String(it) | InlayTooltip::Markdown(it)) => it,
|
LazyProperty::Computed(
|
||||||
Lazy::Lazy => "",
|
InlayTooltip::String(it) | InlayTooltip::Markdown(it),
|
||||||
|
) => it,
|
||||||
|
LazyProperty::Lazy => "",
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.finish(),
|
.finish(),
|
||||||
@ -677,7 +681,7 @@ impl InlayHintLabelBuilder<'_> {
|
|||||||
if !text.is_empty() {
|
if !text.is_empty() {
|
||||||
self.result.parts.push(InlayHintLabelPart {
|
self.result.parts.push(InlayHintLabelPart {
|
||||||
text,
|
text,
|
||||||
linked_location: self.location.take().map(Lazy::Computed),
|
linked_location: self.location.take().map(LazyProperty::Computed),
|
||||||
tooltip: None,
|
tooltip: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -797,7 +801,7 @@ fn ty_to_text_edit(
|
|||||||
ty: &hir::Type,
|
ty: &hir::Type,
|
||||||
offset_to_insert: TextSize,
|
offset_to_insert: TextSize,
|
||||||
prefix: impl Into<String>,
|
prefix: impl Into<String>,
|
||||||
) -> Option<Lazy<TextEdit>> {
|
) -> Option<LazyProperty<TextEdit>> {
|
||||||
// FIXME: Limit the length and bail out on excess somehow?
|
// FIXME: Limit the length and bail out on excess somehow?
|
||||||
let rendered = sema
|
let rendered = sema
|
||||||
.scope(node_for_hint)
|
.scope(node_for_hint)
|
||||||
|
@ -83,7 +83,7 @@ mod tests {
|
|||||||
fixture,
|
fixture,
|
||||||
inlay_hints::{
|
inlay_hints::{
|
||||||
tests::{check_expect, check_with_config, DISABLED_CONFIG, TEST_CONFIG},
|
tests::{check_expect, check_with_config, DISABLED_CONFIG, TEST_CONFIG},
|
||||||
Lazy,
|
LazyProperty,
|
||||||
},
|
},
|
||||||
InlayHintsConfig,
|
InlayHintsConfig,
|
||||||
};
|
};
|
||||||
@ -102,7 +102,7 @@ mod tests {
|
|||||||
let (analysis, file_id) = fixture::file(ra_fixture);
|
let (analysis, file_id) = fixture::file(ra_fixture);
|
||||||
let mut inlay_hints = analysis.inlay_hints(&config, file_id, None).unwrap();
|
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| {
|
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));
|
loc.range = TextRange::empty(TextSize::from(0));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -12,7 +12,7 @@ use syntax::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
inlay_hints::Lazy, InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind,
|
inlay_hints::LazyProperty, InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(super) fn hints(
|
pub(super) fn hints(
|
||||||
@ -143,7 +143,7 @@ pub(super) fn hints(
|
|||||||
acc.push(InlayHint {
|
acc.push(InlayHint {
|
||||||
range: closing_token.text_range(),
|
range: closing_token.text_range(),
|
||||||
kind: InlayKind::ClosingBrace,
|
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,
|
text_edit: None,
|
||||||
position: InlayHintPosition::After,
|
position: InlayHintPosition::After,
|
||||||
pad_left: true,
|
pad_left: true,
|
||||||
|
@ -91,7 +91,7 @@ pub use crate::{
|
|||||||
inlay_hints::{
|
inlay_hints::{
|
||||||
AdjustmentHints, AdjustmentHintsMode, ClosureReturnTypeHints, DiscriminantHints,
|
AdjustmentHints, AdjustmentHintsMode, ClosureReturnTypeHints, DiscriminantHints,
|
||||||
GenericParameterHints, InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart,
|
GenericParameterHints, InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart,
|
||||||
InlayHintPosition, InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints,
|
InlayHintPosition, InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints, LazyProperty
|
||||||
},
|
},
|
||||||
join_lines::JoinLinesConfig,
|
join_lines::JoinLinesConfig,
|
||||||
markup::Markup,
|
markup::Markup,
|
||||||
|
@ -11,8 +11,8 @@ use ide::{
|
|||||||
Annotation, AnnotationKind, Assist, AssistKind, Cancellable, CompletionFieldsToResolve,
|
Annotation, AnnotationKind, Assist, AssistKind, Cancellable, CompletionFieldsToResolve,
|
||||||
CompletionItem, CompletionItemKind, CompletionRelevance, Documentation, FileId, FileRange,
|
CompletionItem, CompletionItemKind, CompletionRelevance, Documentation, FileId, FileRange,
|
||||||
FileSystemEdit, Fold, FoldKind, Highlight, HlMod, HlOperator, HlPunct, HlRange, HlTag, Indel,
|
FileSystemEdit, Fold, FoldKind, Highlight, HlMod, HlOperator, HlPunct, HlRange, HlTag, Indel,
|
||||||
InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayKind, Markup,
|
InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayKind, LazyProperty,
|
||||||
NavigationTarget, ReferenceCategory, RenameError, Runnable, Severity, SignatureHelp,
|
Markup, NavigationTarget, ReferenceCategory, RenameError, Runnable, Severity, SignatureHelp,
|
||||||
SnippetEdit, SourceChange, StructureNodeKind, SymbolKind, TextEdit, TextRange, TextSize,
|
SnippetEdit, SourceChange, StructureNodeKind, SymbolKind, TextEdit, TextRange, TextSize,
|
||||||
};
|
};
|
||||||
use ide_db::{assists, rust_doc::format_docs, FxHasher};
|
use ide_db::{assists, rust_doc::format_docs, FxHasher};
|
||||||
@ -549,12 +549,11 @@ pub(crate) fn inlay_hint(
|
|||||||
) -> Cancellable<lsp_types::InlayHint> {
|
) -> Cancellable<lsp_types::InlayHint> {
|
||||||
let hint_needs_resolve = |hint: &InlayHint| -> Option<TextRange> {
|
let hint_needs_resolve = |hint: &InlayHint| -> Option<TextRange> {
|
||||||
hint.resolve_parent.filter(|_| {
|
hint.resolve_parent.filter(|_| {
|
||||||
hint.text_edit.is_some()
|
hint.text_edit.as_ref().is_some_and(LazyProperty::is_lazy)
|
||||||
|| hint
|
|| hint.label.parts.iter().any(|part| {
|
||||||
.label
|
part.linked_location.as_ref().is_some_and(LazyProperty::is_lazy)
|
||||||
.parts
|
|| part.tooltip.as_ref().is_some_and(LazyProperty::is_lazy)
|
||||||
.iter()
|
})
|
||||||
.any(|part| part.linked_location.is_some() || part.tooltip.is_some())
|
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -569,22 +568,21 @@ pub(crate) fn inlay_hint(
|
|||||||
});
|
});
|
||||||
|
|
||||||
let mut something_to_resolve = false;
|
let mut something_to_resolve = false;
|
||||||
let text_edits = if snap
|
let text_edits = inlay_hint
|
||||||
.config
|
.text_edit
|
||||||
.visual_studio_code_version()
|
.take()
|
||||||
.is_none_or(|version| VersionReq::parse(">=1.86.0").unwrap().matches(version))
|
.and_then(|it| match it {
|
||||||
&& resolve_range_and_hash.is_some()
|
LazyProperty::Computed(it) => Some(it),
|
||||||
&& fields_to_resolve.resolve_text_edits
|
LazyProperty::Lazy => {
|
||||||
{
|
something_to_resolve |=
|
||||||
something_to_resolve |= inlay_hint.text_edit.is_some();
|
snap.config.visual_studio_code_version().is_none_or(|version| {
|
||||||
None
|
VersionReq::parse(">=1.86.0").unwrap().matches(version)
|
||||||
} else {
|
}) && resolve_range_and_hash.is_some()
|
||||||
inlay_hint
|
&& fields_to_resolve.resolve_text_edits;
|
||||||
.text_edit
|
None
|
||||||
.take()
|
}
|
||||||
.and_then(|it| it.computed())
|
})
|
||||||
.map(|it| text_edit_vec(line_index, it))
|
.map(|it| text_edit_vec(line_index, it));
|
||||||
};
|
|
||||||
let (label, tooltip) = inlay_hint_label(
|
let (label, tooltip) = inlay_hint_label(
|
||||||
snap,
|
snap,
|
||||||
fields_to_resolve,
|
fields_to_resolve,
|
||||||
@ -637,22 +635,23 @@ fn inlay_hint_label(
|
|||||||
let (label, tooltip) = match &*label.parts {
|
let (label, tooltip) = match &*label.parts {
|
||||||
[InlayHintLabelPart { linked_location: None, .. }] => {
|
[InlayHintLabelPart { linked_location: None, .. }] => {
|
||||||
let InlayHintLabelPart { text, tooltip, .. } = label.parts.pop().unwrap();
|
let InlayHintLabelPart { text, tooltip, .. } = label.parts.pop().unwrap();
|
||||||
let hint_tooltip = if needs_resolve && fields_to_resolve.resolve_hint_tooltip {
|
let tooltip = tooltip.and_then(|it| match it {
|
||||||
*something_to_resolve |= tooltip.is_some();
|
LazyProperty::Computed(it) => Some(it),
|
||||||
None
|
LazyProperty::Lazy => {
|
||||||
} else {
|
*something_to_resolve |=
|
||||||
match tooltip.and_then(|it| it.computed()) {
|
needs_resolve && fields_to_resolve.resolve_hint_tooltip;
|
||||||
Some(ide::InlayTooltip::String(s)) => {
|
None
|
||||||
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 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)
|
(lsp_types::InlayHintLabel::String(text), hint_tooltip)
|
||||||
}
|
}
|
||||||
@ -661,34 +660,38 @@ fn inlay_hint_label(
|
|||||||
.parts
|
.parts
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|part| {
|
.map(|part| {
|
||||||
let tooltip = if needs_resolve && fields_to_resolve.resolve_label_tooltip {
|
let tooltip = part.tooltip.and_then(|it| match it {
|
||||||
*something_to_resolve |= part.tooltip.is_some();
|
LazyProperty::Computed(it) => Some(it),
|
||||||
None
|
LazyProperty::Lazy => {
|
||||||
} else {
|
*something_to_resolve |= fields_to_resolve.resolve_label_tooltip;
|
||||||
match part.tooltip.and_then(|it| it.computed()) {
|
None
|
||||||
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 = 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 {
|
let location = part
|
||||||
*something_to_resolve |= part.linked_location.is_some();
|
.linked_location
|
||||||
None
|
.and_then(|it| match it {
|
||||||
} else {
|
LazyProperty::Computed(it) => Some(it),
|
||||||
part.linked_location
|
LazyProperty::Lazy => {
|
||||||
.and_then(|it| it.computed())
|
*something_to_resolve |= fields_to_resolve.resolve_label_location;
|
||||||
.map(|range| location(snap, range))
|
None
|
||||||
.transpose()?
|
}
|
||||||
};
|
})
|
||||||
|
.map(|range| location(snap, range))
|
||||||
|
.transpose()?;
|
||||||
Ok(lsp_types::InlayHintLabelPart {
|
Ok(lsp_types::InlayHintLabelPart {
|
||||||
value: part.text,
|
value: part.text,
|
||||||
tooltip,
|
tooltip,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user