Allow inlay hint tooltips to trigger hovers

This commit is contained in:
Lukas Wirth 2022-05-17 14:46:43 +02:00
parent a2ec010185
commit 21f37a6d9e
5 changed files with 80 additions and 60 deletions

View file

@ -48,7 +48,7 @@ pub enum ReborrowHints {
pub enum InlayKind { pub enum InlayKind {
BindingModeHint, BindingModeHint,
ChainingHint, ChainingHint,
ClosingBraceHint(Option<TextSize>), ClosingBraceHint,
ClosureReturnTypeHint, ClosureReturnTypeHint,
GenericParamListHint, GenericParamListHint,
ImplicitReborrowHint, ImplicitReborrowHint,
@ -57,11 +57,19 @@ pub enum InlayKind {
TypeHint, TypeHint,
} }
// FIXME: This should live somewhere more general
#[derive(Debug)]
pub enum RangeOrOffset {
Range(TextRange),
Offset(TextSize),
}
#[derive(Debug)] #[derive(Debug)]
pub struct InlayHint { pub struct InlayHint {
pub range: TextRange, pub range: TextRange,
pub kind: InlayKind, pub kind: InlayKind,
pub label: String, pub label: String,
pub hover_trigger: Option<RangeOrOffset>,
} }
// Feature: Inlay Hints // Feature: Inlay Hints
@ -253,8 +261,9 @@ fn closing_brace_hints(
acc.push(InlayHint { acc.push(InlayHint {
range: closing_token.text_range(), range: closing_token.text_range(),
kind: InlayKind::ClosingBraceHint(name_offset), kind: InlayKind::ClosingBraceHint,
label, label,
hover_trigger: name_offset.map(RangeOrOffset::Offset),
}); });
None None
@ -273,6 +282,7 @@ fn lifetime_fn_hints(
range: t.text_range(), range: t.text_range(),
kind: InlayKind::LifetimeHint, kind: InlayKind::LifetimeHint,
label, label,
hover_trigger: None,
}; };
let param_list = func.param_list()?; let param_list = func.param_list()?;
@ -431,6 +441,7 @@ fn lifetime_fn_hints(
range: func.name()?.syntax().text_range(), range: func.name()?.syntax().text_range(),
kind: InlayKind::GenericParamListHint, kind: InlayKind::GenericParamListHint,
label: format!("<{}>", allocated_lifetimes.iter().format(", "),).into(), label: format!("<{}>", allocated_lifetimes.iter().format(", "),).into(),
hover_trigger: None,
}), }),
} }
Some(()) Some(())
@ -464,6 +475,7 @@ fn closure_ret_hints(
kind: InlayKind::ClosureReturnTypeHint, kind: InlayKind::ClosureReturnTypeHint,
label: hint_iterator(sema, &famous_defs, config, &ty) label: hint_iterator(sema, &famous_defs, config, &ty)
.unwrap_or_else(|| ty.display_truncated(sema.db, config.max_length).to_string()), .unwrap_or_else(|| ty.display_truncated(sema.db, config.max_length).to_string()),
hover_trigger: None,
}); });
Some(()) Some(())
} }
@ -490,6 +502,7 @@ fn reborrow_hints(
range: expr.syntax().text_range(), range: expr.syntax().text_range(),
kind: InlayKind::ImplicitReborrowHint, kind: InlayKind::ImplicitReborrowHint,
label: label.to_string(), label: label.to_string(),
hover_trigger: None,
}); });
Some(()) Some(())
} }
@ -548,6 +561,7 @@ fn chaining_hints(
label: hint_iterator(sema, &famous_defs, config, &ty).unwrap_or_else(|| { label: hint_iterator(sema, &famous_defs, config, &ty).unwrap_or_else(|| {
ty.display_truncated(sema.db, config.max_length).to_string() ty.display_truncated(sema.db, config.max_length).to_string()
}), }),
hover_trigger: Some(RangeOrOffset::Range(expr.syntax().text_range())),
}); });
} }
} }
@ -588,6 +602,8 @@ fn param_name_hints(
range, range,
kind: InlayKind::ParameterHint, kind: InlayKind::ParameterHint,
label: param_name.into(), label: param_name.into(),
// FIXME: Show hover for parameter
hover_trigger: None,
}); });
acc.extend(hints); acc.extend(hints);
@ -613,7 +629,12 @@ fn binding_mode_hints(
(true, false) => "&", (true, false) => "&",
_ => return, _ => return,
}; };
acc.push(InlayHint { range, kind: InlayKind::BindingModeHint, label: r.to_string() }); acc.push(InlayHint {
range,
kind: InlayKind::BindingModeHint,
label: r.to_string(),
hover_trigger: None,
});
}); });
match pat { match pat {
ast::Pat::IdentPat(pat) if pat.ref_token().is_none() && pat.mut_token().is_none() => { ast::Pat::IdentPat(pat) if pat.ref_token().is_none() && pat.mut_token().is_none() => {
@ -623,7 +644,12 @@ fn binding_mode_hints(
hir::BindingMode::Ref(Mutability::Mut) => "ref mut", hir::BindingMode::Ref(Mutability::Mut) => "ref mut",
hir::BindingMode::Ref(Mutability::Shared) => "ref", hir::BindingMode::Ref(Mutability::Shared) => "ref",
}; };
acc.push(InlayHint { range, kind: InlayKind::BindingModeHint, label: bm.to_string() }); acc.push(InlayHint {
range,
kind: InlayKind::BindingModeHint,
label: bm.to_string(),
hover_trigger: None,
});
} }
_ => (), _ => (),
} }
@ -673,6 +699,7 @@ fn bind_pat_hints(
}, },
kind: InlayKind::TypeHint, kind: InlayKind::TypeHint,
label, label,
hover_trigger: pat.name().map(|it| it.syntax().text_range()).map(RangeOrOffset::Range),
}); });
Some(()) Some(())

View file

@ -80,7 +80,9 @@ pub use crate::{
folding_ranges::{Fold, FoldKind}, folding_ranges::{Fold, FoldKind},
highlight_related::{HighlightRelatedConfig, HighlightedRange}, highlight_related::{HighlightRelatedConfig, HighlightedRange},
hover::{HoverAction, HoverConfig, HoverDocFormat, HoverGotoTypeData, HoverResult}, hover::{HoverAction, HoverConfig, HoverDocFormat, HoverGotoTypeData, HoverResult},
inlay_hints::{InlayHint, InlayHintsConfig, InlayKind, LifetimeElisionHints, ReborrowHints}, inlay_hints::{
InlayHint, InlayHintsConfig, InlayKind, LifetimeElisionHints, RangeOrOffset, ReborrowHints,
},
join_lines::JoinLinesConfig, join_lines::JoinLinesConfig,
markup::Markup, markup::Markup,
moniker::{MonikerKind, MonikerResult, PackageInformation}, moniker::{MonikerKind, MonikerResult, PackageInformation},

View file

@ -1360,21 +1360,23 @@ pub(crate) fn handle_inlay_hints_resolve(
mut hint: InlayHint, mut hint: InlayHint,
) -> Result<InlayHint> { ) -> Result<InlayHint> {
let _p = profile::span("handle_inlay_hints_resolve"); let _p = profile::span("handle_inlay_hints_resolve");
let succ = (|| {
let data = match hint.data.take() { let data = match hint.data.take() {
Some(it) => it, Some(it) => it,
None => return Ok(None), None => return Ok(hint),
}; };
let resolve_data: lsp_ext::InlayHintResolveData = serde_json::from_value(data)?; let resolve_data: lsp_ext::InlayHintResolveData = serde_json::from_value(data)?;
let file_range = from_proto::file_range( let file_range = from_proto::file_range(
&snap, &snap,
resolve_data.position.text_document, resolve_data.text_document,
Range::new(resolve_data.position.position, resolve_data.position.position), match resolve_data.position {
PositionOrRange::Position(pos) => Range::new(pos, pos),
PositionOrRange::Range(range) => range,
},
)?; )?;
let info = match snap.analysis.hover(&snap.config.hover(), file_range)? { let info = match snap.analysis.hover(&snap.config.hover(), file_range)? {
None => return Ok(None), None => return Ok(hint),
Some(info) => info, Some(info) => info,
}; };
@ -1386,20 +1388,6 @@ pub(crate) fn handle_inlay_hints_resolve(
info.info.markup, info.info.markup,
markup_kind, markup_kind,
))); )));
Result::<_, crate::Error>::Ok(Some(()))
})()?
.is_some();
if !succ {
if let lsp_types::InlayHintLabel::String(s) = &hint.label {
hint.tooltip =
Some(lsp_types::InlayHintTooltip::MarkupContent(lsp_types::MarkupContent {
kind: lsp_types::MarkupKind::PlainText,
value: s.clone(),
}));
}
}
Ok(hint) Ok(hint)
} }

View file

@ -520,7 +520,8 @@ pub struct CompletionResolveData {
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct InlayHintResolveData { pub struct InlayHintResolveData {
pub position: lsp_types::TextDocumentPositionParams, pub text_document: TextDocumentIdentifier,
pub position: PositionOrRange,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]

View file

@ -432,11 +432,11 @@ pub(crate) fn inlay_hint(
| InlayKind::ChainingHint | InlayKind::ChainingHint
| InlayKind::GenericParamListHint | InlayKind::GenericParamListHint
| InlayKind::LifetimeHint | InlayKind::LifetimeHint
| InlayKind::ClosingBraceHint(_) => position(line_index, inlay_hint.range.end()), | InlayKind::ClosingBraceHint => position(line_index, inlay_hint.range.end()),
}, },
padding_left: Some(match inlay_hint.kind { padding_left: Some(match inlay_hint.kind {
InlayKind::TypeHint => !render_colons, InlayKind::TypeHint => !render_colons,
InlayKind::ChainingHint | InlayKind::ClosingBraceHint(_) => true, InlayKind::ChainingHint | InlayKind::ClosingBraceHint => true,
InlayKind::BindingModeHint InlayKind::BindingModeHint
| InlayKind::ClosureReturnTypeHint | InlayKind::ClosureReturnTypeHint
| InlayKind::GenericParamListHint | InlayKind::GenericParamListHint
@ -450,7 +450,7 @@ pub(crate) fn inlay_hint(
| InlayKind::GenericParamListHint | InlayKind::GenericParamListHint
| InlayKind::ImplicitReborrowHint | InlayKind::ImplicitReborrowHint
| InlayKind::TypeHint | InlayKind::TypeHint
| InlayKind::ClosingBraceHint(_) => false, | InlayKind::ClosingBraceHint => false,
InlayKind::BindingModeHint => inlay_hint.label != "&", InlayKind::BindingModeHint => inlay_hint.label != "&",
InlayKind::ParameterHint | InlayKind::LifetimeHint => true, InlayKind::ParameterHint | InlayKind::LifetimeHint => true,
}), }),
@ -458,7 +458,7 @@ pub(crate) fn inlay_hint(
InlayKind::ParameterHint if render_colons => format!("{}:", inlay_hint.label), InlayKind::ParameterHint if render_colons => format!("{}:", inlay_hint.label),
InlayKind::TypeHint if render_colons => format!(": {}", inlay_hint.label), InlayKind::TypeHint if render_colons => format!(": {}", inlay_hint.label),
InlayKind::ClosureReturnTypeHint => format!(" -> {}", inlay_hint.label), InlayKind::ClosureReturnTypeHint => format!(" -> {}", inlay_hint.label),
_ => inlay_hint.label, _ => inlay_hint.label.clone(),
}), }),
kind: match inlay_hint.kind { kind: match inlay_hint.kind {
InlayKind::ParameterHint => Some(lsp_types::InlayHintKind::PARAMETER), InlayKind::ParameterHint => Some(lsp_types::InlayHintKind::PARAMETER),
@ -469,22 +469,24 @@ pub(crate) fn inlay_hint(
| InlayKind::GenericParamListHint | InlayKind::GenericParamListHint
| InlayKind::LifetimeHint | InlayKind::LifetimeHint
| InlayKind::ImplicitReborrowHint | InlayKind::ImplicitReborrowHint
| InlayKind::ClosingBraceHint(_) => None, | InlayKind::ClosingBraceHint => None,
}, },
text_edits: None, text_edits: None,
tooltip: None, tooltip: Some(lsp_types::InlayHintTooltip::String(inlay_hint.label)),
data: match inlay_hint.kind { data: inlay_hint.hover_trigger.map(|range_or_offset| {
InlayKind::ClosingBraceHint(Some(offset)) => Some(
to_value(lsp_ext::InlayHintResolveData { to_value(lsp_ext::InlayHintResolveData {
position: lsp_types::TextDocumentPositionParams {
text_document: text_document.clone(), text_document: text_document.clone(),
position: position(line_index, offset), position: match range_or_offset {
ide::RangeOrOffset::Offset(offset) => {
lsp_ext::PositionOrRange::Position(position(line_index, offset))
}
ide::RangeOrOffset::Range(text_range) => {
lsp_ext::PositionOrRange::Range(range(line_index, text_range))
}
}, },
}) })
.unwrap(), .unwrap()
), }),
_ => None,
},
} }
} }