From 91833f19747738ba0ebf50357a73e62d15b127f2 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 17 May 2022 12:49:51 +0200 Subject: [PATCH 1/6] feat: Implement inlay hint tooltips --- crates/rust-analyzer/src/caps.rs | 10 ++++++++-- crates/rust-analyzer/src/handlers.rs | 13 +++++++++++++ crates/rust-analyzer/src/main_loop.rs | 1 + 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs index 85e3d5005386..a653ec289b38 100644 --- a/crates/rust-analyzer/src/caps.rs +++ b/crates/rust-analyzer/src/caps.rs @@ -4,7 +4,8 @@ use lsp_types::{ CodeActionProviderCapability, CodeLensOptions, CompletionOptions, DeclarationCapability, DocumentOnTypeFormattingOptions, FileOperationFilter, FileOperationPattern, FileOperationPatternKind, FileOperationRegistrationOptions, FoldingRangeProviderCapability, - HoverProviderCapability, ImplementationProviderCapability, OneOf, RenameOptions, SaveOptions, + HoverProviderCapability, ImplementationProviderCapability, InlayHintOptions, + InlayHintServerCapabilities, OneOf, RenameOptions, SaveOptions, SelectionRangeProviderCapability, SemanticTokensFullOptions, SemanticTokensLegend, SemanticTokensOptions, ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind, TextDocumentSyncOptions, TypeDefinitionProviderCapability, @@ -112,7 +113,12 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities { .into(), ), moniker_provider: None, - inlay_hint_provider: Some(OneOf::Left(true)), + inlay_hint_provider: Some(OneOf::Right(InlayHintServerCapabilities::Options( + InlayHintOptions { + work_done_progress_options: Default::default(), + resolve_provider: Some(true), + }, + ))), experimental: Some(json!({ "externalDocs": true, "hoverRange": true, diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index ec897ec9d955..e832f4b45a0c 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs @@ -1348,6 +1348,19 @@ pub(crate) fn handle_inlay_hints( )) } +pub(crate) fn handle_inlay_hints_resolve( + _snap: GlobalStateSnapshot, + mut hint: InlayHint, +) -> Result { + 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) +} + pub(crate) fn handle_call_hierarchy_prepare( snap: GlobalStateSnapshot, params: CallHierarchyPrepareParams, diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 856948a01273..b5ac55e60d6b 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -612,6 +612,7 @@ impl GlobalState { .on::(handlers::handle_goto_implementation) .on::(handlers::handle_goto_type_definition) .on::(handlers::handle_inlay_hints) + .on::(handlers::handle_inlay_hints_resolve) .on::(handlers::handle_completion) .on::(handlers::handle_completion_resolve) .on::(handlers::handle_code_lens) From 0756719a305c1da552b980d0f05fa844f0194ed7 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 17 May 2022 12:56:14 +0200 Subject: [PATCH 2/6] Replace some SmolStr usages with String as the conversion happens anyways --- crates/ide/src/inlay_hints.rs | 59 ++++++++++++---------------- crates/rust-analyzer/src/to_proto.rs | 36 ++++++++--------- 2 files changed, 44 insertions(+), 51 deletions(-) diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index d3ce350f9b3e..343a8f7acce3 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -8,7 +8,7 @@ use itertools::Itertools; use stdx::to_lower_snake_case; use syntax::{ ast::{self, AstNode, HasArgList, HasGenericParams, HasName, UnaryOp}, - match_ast, Direction, NodeOrToken, SmolStr, SyntaxKind, SyntaxNode, TextRange, T, + match_ast, Direction, NodeOrToken, SmolStr, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, T, }; use crate::FileId; @@ -60,7 +60,7 @@ pub enum InlayKind { pub struct InlayHint { pub range: TextRange, pub kind: InlayKind, - pub label: SmolStr, + pub label: String, } // Feature: Inlay Hints @@ -248,7 +248,7 @@ fn closing_brace_hints( acc.push(InlayHint { range: closing_token.text_range(), kind: InlayKind::ClosingBraceHint, - label: label.into(), + label, }); None @@ -262,6 +262,13 @@ fn lifetime_fn_hints( if config.lifetime_elision_hints == LifetimeElisionHints::Never { return None; } + + let mk_lt_hint = |t: SyntaxToken, label| InlayHint { + range: t.text_range(), + kind: InlayKind::LifetimeHint, + label, + }; + let param_list = func.param_list()?; let generic_param_list = func.generic_param_list(); let ret_type = func.ret_type(); @@ -378,11 +385,7 @@ fn lifetime_fn_hints( ast::Type::RefType(ty) if ty.lifetime().is_none() => { if let Some(amp) = ty.amp_token() { is_trivial = false; - acc.push(InlayHint { - range: amp.text_range(), - kind: InlayKind::LifetimeHint, - label: output_lt.clone(), - }); + acc.push(mk_lt_hint(amp, output_lt.to_string())); } } _ => (), @@ -398,8 +401,8 @@ fn lifetime_fn_hints( for (_, amp_token, _, is_elided) in potential_lt_refs { if is_elided { let t = amp_token?; - let lt = a.next()?.clone(); - acc.push(InlayHint { range: t.text_range(), kind: InlayKind::LifetimeHint, label: lt }); + let lt = a.next()?; + acc.push(mk_lt_hint(t, lt.to_string())); } } @@ -409,16 +412,14 @@ fn lifetime_fn_hints( (Some(gpl), allocated_lifetimes) => { let angle_tok = gpl.l_angle_token()?; let is_empty = gpl.generic_params().next().is_none(); - acc.push(InlayHint { - range: angle_tok.text_range(), - kind: InlayKind::GenericParamListHint, - label: format!( + acc.push(mk_lt_hint( + angle_tok, + format!( "{}{}", allocated_lifetimes.iter().format(", "), if is_empty { "" } else { ", " } - ) - .into(), - }); + ), + )); } (None, allocated_lifetimes) => acc.push(InlayHint { range: func.name()?.syntax().text_range(), @@ -456,7 +457,7 @@ fn closure_ret_hints( range: param_list.syntax().text_range(), kind: InlayKind::ClosureReturnTypeHint, label: hint_iterator(sema, &famous_defs, config, &ty) - .unwrap_or_else(|| ty.display_truncated(sema.db, config.max_length).to_string().into()), + .unwrap_or_else(|| ty.display_truncated(sema.db, config.max_length).to_string()), }); Some(()) } @@ -482,7 +483,7 @@ fn reborrow_hints( acc.push(InlayHint { range: expr.syntax().text_range(), kind: InlayKind::ImplicitReborrowHint, - label: SmolStr::new_inline(label), + label: label.to_string(), }); Some(()) } @@ -539,7 +540,7 @@ fn chaining_hints( range: expr.syntax().text_range(), kind: InlayKind::ChainingHint, label: hint_iterator(sema, &famous_defs, config, &ty).unwrap_or_else(|| { - ty.display_truncated(sema.db, config.max_length).to_string().into() + ty.display_truncated(sema.db, config.max_length).to_string() }), }); } @@ -606,11 +607,7 @@ fn binding_mode_hints( (true, false) => "&", _ => return, }; - acc.push(InlayHint { - range, - kind: InlayKind::BindingModeHint, - label: SmolStr::new_inline(r), - }); + acc.push(InlayHint { range, kind: InlayKind::BindingModeHint, label: r.to_string() }); }); match pat { ast::Pat::IdentPat(pat) if pat.ref_token().is_none() && pat.mut_token().is_none() => { @@ -620,11 +617,7 @@ fn binding_mode_hints( hir::BindingMode::Ref(Mutability::Mut) => "ref mut", hir::BindingMode::Ref(Mutability::Shared) => "ref", }; - acc.push(InlayHint { - range, - kind: InlayKind::BindingModeHint, - label: SmolStr::new_inline(bm), - }); + acc.push(InlayHint { range, kind: InlayKind::BindingModeHint, label: bm.to_string() }); } _ => (), } @@ -663,7 +656,7 @@ fn bind_pat_hints( { return None; } - ty_name.into() + ty_name } }; @@ -738,7 +731,7 @@ fn hint_iterator( famous_defs: &FamousDefs, config: &InlayHintsConfig, ty: &hir::Type, -) -> Option { +) -> Option { let db = sema.db; let strukt = ty.strip_references().as_adt()?; let krate = strukt.module(db).krate(); @@ -775,7 +768,7 @@ fn hint_iterator( ) .to_string() }); - return Some(format!("{}{}{}", LABEL_START, ty_display, LABEL_END).into()); + return Some(format!("{}{}{}", LABEL_START, ty_display, LABEL_END)); } } diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index c0609f518748..83d863ce36b8 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs @@ -433,24 +433,6 @@ pub(crate) fn inlay_hint( | InlayKind::LifetimeHint | InlayKind::ClosingBraceHint => position(line_index, inlay_hint.range.end()), }, - label: lsp_types::InlayHintLabel::String(match inlay_hint.kind { - InlayKind::ParameterHint if render_colons => format!("{}:", inlay_hint.label), - InlayKind::TypeHint if render_colons => format!(": {}", inlay_hint.label), - InlayKind::ClosureReturnTypeHint => format!(" -> {}", inlay_hint.label), - _ => inlay_hint.label.to_string(), - }), - kind: match inlay_hint.kind { - InlayKind::ParameterHint => Some(lsp_types::InlayHintKind::PARAMETER), - InlayKind::ClosureReturnTypeHint | InlayKind::TypeHint | InlayKind::ChainingHint => { - Some(lsp_types::InlayHintKind::TYPE) - } - InlayKind::BindingModeHint - | InlayKind::GenericParamListHint - | InlayKind::LifetimeHint - | InlayKind::ImplicitReborrowHint - | InlayKind::ClosingBraceHint => None, - }, - tooltip: None, padding_left: Some(match inlay_hint.kind { InlayKind::TypeHint => !render_colons, InlayKind::ChainingHint | InlayKind::ClosingBraceHint => true, @@ -471,7 +453,25 @@ pub(crate) fn inlay_hint( InlayKind::BindingModeHint => inlay_hint.label != "&", InlayKind::ParameterHint | InlayKind::LifetimeHint => true, }), + label: lsp_types::InlayHintLabel::String(match inlay_hint.kind { + InlayKind::ParameterHint if render_colons => format!("{}:", inlay_hint.label), + InlayKind::TypeHint if render_colons => format!(": {}", inlay_hint.label), + InlayKind::ClosureReturnTypeHint => format!(" -> {}", inlay_hint.label), + _ => inlay_hint.label, + }), + kind: match inlay_hint.kind { + InlayKind::ParameterHint => Some(lsp_types::InlayHintKind::PARAMETER), + InlayKind::ClosureReturnTypeHint | InlayKind::TypeHint | InlayKind::ChainingHint => { + Some(lsp_types::InlayHintKind::TYPE) + } + InlayKind::BindingModeHint + | InlayKind::GenericParamListHint + | InlayKind::LifetimeHint + | InlayKind::ImplicitReborrowHint + | InlayKind::ClosingBraceHint => None, + }, text_edits: None, + tooltip: None, data: None, } } From a2ec0101853f4821a47279144669fc4ede713bed Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 17 May 2022 13:39:45 +0200 Subject: [PATCH 3/6] Trigger hover requests on closing brace hints --- crates/ide/src/inlay_hints.rs | 32 +++++++++------- crates/rust-analyzer/src/handlers.rs | 56 ++++++++++++++++++++++++---- crates/rust-analyzer/src/lsp_ext.rs | 5 +++ crates/rust-analyzer/src/to_proto.rs | 24 +++++++++--- 4 files changed, 91 insertions(+), 26 deletions(-) diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 343a8f7acce3..4684f92ae8d4 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -8,7 +8,8 @@ use itertools::Itertools; use stdx::to_lower_snake_case; use syntax::{ ast::{self, AstNode, HasArgList, HasGenericParams, HasName, UnaryOp}, - match_ast, Direction, NodeOrToken, SmolStr, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, T, + match_ast, Direction, NodeOrToken, SmolStr, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, + TextSize, T, }; use crate::FileId; @@ -47,7 +48,7 @@ pub enum ReborrowHints { pub enum InlayKind { BindingModeHint, ChainingHint, - ClosingBraceHint, + ClosingBraceHint(Option), ClosureReturnTypeHint, GenericParamListHint, ImplicitReborrowHint, @@ -164,8 +165,10 @@ fn closing_brace_hints( ) -> Option<()> { let min_lines = config.closing_brace_hints_min_lines?; + let name = |it: ast::Name| it.syntax().text_range().start(); + let mut closing_token; - let label = if let Some(item_list) = ast::AssocItemList::cast(node.clone()) { + let (label, name_offset) = if let Some(item_list) = ast::AssocItemList::cast(node.clone()) { closing_token = item_list.r_curly_token()?; let parent = item_list.syntax().parent()?; @@ -176,13 +179,13 @@ fn closing_brace_hints( let ty = imp.self_ty(sema.db); let trait_ = imp.trait_(sema.db); - match trait_ { + (match trait_ { Some(tr) => format!("impl {} for {}", tr.name(sema.db), ty.display_truncated(sema.db, config.max_length)), None => format!("impl {}", ty.display_truncated(sema.db, config.max_length)), - } + }, None) }, ast::Trait(tr) => { - format!("trait {}", tr.name()?) + (format!("trait {}", tr.name()?), tr.name().map(name)) }, _ => return None, } @@ -191,7 +194,7 @@ fn closing_brace_hints( closing_token = list.r_curly_token()?; let module = ast::Module::cast(list.syntax().parent()?)?; - format!("mod {}", module.name()?) + (format!("mod {}", module.name()?), module.name().map(name)) } else if let Some(block) = ast::BlockExpr::cast(node.clone()) { closing_token = block.stmt_list()?.r_curly_token()?; @@ -201,14 +204,14 @@ fn closing_brace_hints( ast::Fn(it) => { // FIXME: this could include parameters, but `HirDisplay` prints too much info // and doesn't respect the max length either, so the hints end up way too long - format!("fn {}", it.name()?) + (format!("fn {}", it.name()?), it.name().map(name)) }, - ast::Static(it) => format!("static {}", it.name()?), + ast::Static(it) => (format!("static {}", it.name()?), it.name().map(name)), ast::Const(it) => { if it.underscore_token().is_some() { - "const _".into() + ("const _".into(), None) } else { - format!("const {}", it.name()?) + (format!("const {}", it.name()?), it.name().map(name)) } }, _ => return None, @@ -221,7 +224,10 @@ fn closing_brace_hints( } closing_token = last_token; - format!("{}!", mac.path()?) + ( + format!("{}!", mac.path()?), + mac.path().and_then(|it| it.segment()).map(|it| it.syntax().text_range().start()), + ) } else { return None; }; @@ -247,7 +253,7 @@ fn closing_brace_hints( acc.push(InlayHint { range: closing_token.text_range(), - kind: InlayKind::ClosingBraceHint, + kind: InlayKind::ClosingBraceHint(name_offset), label, }); diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index e832f4b45a0c..95a6f4f1945d 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs @@ -1343,21 +1343,63 @@ pub(crate) fn handle_inlay_hints( snap.analysis .inlay_hints(&inlay_hints_config, file_id, Some(range))? .into_iter() - .map(|it| to_proto::inlay_hint(inlay_hints_config.render_colons, &line_index, it)) + .map(|it| { + to_proto::inlay_hint( + &line_index, + ¶ms.text_document, + inlay_hints_config.render_colons, + it, + ) + }) .collect(), )) } pub(crate) fn handle_inlay_hints_resolve( - _snap: GlobalStateSnapshot, + snap: GlobalStateSnapshot, mut hint: InlayHint, ) -> Result { - 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(), - })); + let _p = profile::span("handle_inlay_hints_resolve"); + let succ = (|| { + let data = match hint.data.take() { + Some(it) => it, + None => return Ok(None), + }; + + let resolve_data: lsp_ext::InlayHintResolveData = serde_json::from_value(data)?; + + let file_range = from_proto::file_range( + &snap, + resolve_data.position.text_document, + Range::new(resolve_data.position.position, resolve_data.position.position), + )?; + let info = match snap.analysis.hover(&snap.config.hover(), file_range)? { + None => return Ok(None), + Some(info) => info, + }; + + let markup_kind = + snap.config.hover().documentation.map_or(ide::HoverDocFormat::Markdown, |kind| kind); + + // FIXME: hover actions? + hint.tooltip = Some(lsp_types::InlayHintTooltip::MarkupContent(to_proto::markup_content( + info.info.markup, + 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) } diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs index 1cfaa1332742..8e7e2e236429 100644 --- a/crates/rust-analyzer/src/lsp_ext.rs +++ b/crates/rust-analyzer/src/lsp_ext.rs @@ -518,6 +518,11 @@ pub struct CompletionResolveData { pub imports: Vec, } +#[derive(Debug, Serialize, Deserialize)] +pub struct InlayHintResolveData { + pub position: lsp_types::TextDocumentPositionParams, +} + #[derive(Debug, Serialize, Deserialize)] pub struct CompletionImport { pub full_import_path: String, diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 83d863ce36b8..9287d7c53e3c 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs @@ -415,8 +415,9 @@ pub(crate) fn signature_help( } pub(crate) fn inlay_hint( - render_colons: bool, line_index: &LineIndex, + text_document: &lsp_types::TextDocumentIdentifier, + render_colons: bool, inlay_hint: InlayHint, ) -> lsp_types::InlayHint { lsp_types::InlayHint { @@ -431,11 +432,11 @@ pub(crate) fn inlay_hint( | InlayKind::ChainingHint | InlayKind::GenericParamListHint | 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 { InlayKind::TypeHint => !render_colons, - InlayKind::ChainingHint | InlayKind::ClosingBraceHint => true, + InlayKind::ChainingHint | InlayKind::ClosingBraceHint(_) => true, InlayKind::BindingModeHint | InlayKind::ClosureReturnTypeHint | InlayKind::GenericParamListHint @@ -449,7 +450,7 @@ pub(crate) fn inlay_hint( | InlayKind::GenericParamListHint | InlayKind::ImplicitReborrowHint | InlayKind::TypeHint - | InlayKind::ClosingBraceHint => false, + | InlayKind::ClosingBraceHint(_) => false, InlayKind::BindingModeHint => inlay_hint.label != "&", InlayKind::ParameterHint | InlayKind::LifetimeHint => true, }), @@ -468,11 +469,22 @@ pub(crate) fn inlay_hint( | InlayKind::GenericParamListHint | InlayKind::LifetimeHint | InlayKind::ImplicitReborrowHint - | InlayKind::ClosingBraceHint => None, + | InlayKind::ClosingBraceHint(_) => None, }, text_edits: None, tooltip: None, - data: None, + data: match inlay_hint.kind { + InlayKind::ClosingBraceHint(Some(offset)) => Some( + to_value(lsp_ext::InlayHintResolveData { + position: lsp_types::TextDocumentPositionParams { + text_document: text_document.clone(), + position: position(line_index, offset), + }, + }) + .unwrap(), + ), + _ => None, + }, } } From 21f37a6d9e45055f8a9bcf699f923d193c61fe82 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 17 May 2022 14:46:43 +0200 Subject: [PATCH 4/6] Allow inlay hint tooltips to trigger hovers --- crates/ide/src/inlay_hints.rs | 35 ++++++++++++++-- crates/ide/src/lib.rs | 4 +- crates/rust-analyzer/src/handlers.rs | 60 +++++++++++----------------- crates/rust-analyzer/src/lsp_ext.rs | 3 +- crates/rust-analyzer/src/to_proto.rs | 38 +++++++++--------- 5 files changed, 80 insertions(+), 60 deletions(-) diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 4684f92ae8d4..e84338f0c821 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -48,7 +48,7 @@ pub enum ReborrowHints { pub enum InlayKind { BindingModeHint, ChainingHint, - ClosingBraceHint(Option), + ClosingBraceHint, ClosureReturnTypeHint, GenericParamListHint, ImplicitReborrowHint, @@ -57,11 +57,19 @@ pub enum InlayKind { TypeHint, } +// FIXME: This should live somewhere more general +#[derive(Debug)] +pub enum RangeOrOffset { + Range(TextRange), + Offset(TextSize), +} + #[derive(Debug)] pub struct InlayHint { pub range: TextRange, pub kind: InlayKind, pub label: String, + pub hover_trigger: Option, } // Feature: Inlay Hints @@ -253,8 +261,9 @@ fn closing_brace_hints( acc.push(InlayHint { range: closing_token.text_range(), - kind: InlayKind::ClosingBraceHint(name_offset), + kind: InlayKind::ClosingBraceHint, label, + hover_trigger: name_offset.map(RangeOrOffset::Offset), }); None @@ -273,6 +282,7 @@ fn lifetime_fn_hints( range: t.text_range(), kind: InlayKind::LifetimeHint, label, + hover_trigger: None, }; let param_list = func.param_list()?; @@ -431,6 +441,7 @@ fn lifetime_fn_hints( range: func.name()?.syntax().text_range(), kind: InlayKind::GenericParamListHint, label: format!("<{}>", allocated_lifetimes.iter().format(", "),).into(), + hover_trigger: None, }), } Some(()) @@ -464,6 +475,7 @@ fn closure_ret_hints( kind: InlayKind::ClosureReturnTypeHint, label: hint_iterator(sema, &famous_defs, config, &ty) .unwrap_or_else(|| ty.display_truncated(sema.db, config.max_length).to_string()), + hover_trigger: None, }); Some(()) } @@ -490,6 +502,7 @@ fn reborrow_hints( range: expr.syntax().text_range(), kind: InlayKind::ImplicitReborrowHint, label: label.to_string(), + hover_trigger: None, }); Some(()) } @@ -548,6 +561,7 @@ fn chaining_hints( label: hint_iterator(sema, &famous_defs, config, &ty).unwrap_or_else(|| { 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, kind: InlayKind::ParameterHint, label: param_name.into(), + // FIXME: Show hover for parameter + hover_trigger: None, }); acc.extend(hints); @@ -613,7 +629,12 @@ fn binding_mode_hints( (true, false) => "&", _ => 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 { 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::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, label, + hover_trigger: pat.name().map(|it| it.syntax().text_range()).map(RangeOrOffset::Range), }); Some(()) diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index e5160f99f34b..071da8097c50 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -80,7 +80,9 @@ pub use crate::{ folding_ranges::{Fold, FoldKind}, highlight_related::{HighlightRelatedConfig, HighlightedRange}, hover::{HoverAction, HoverConfig, HoverDocFormat, HoverGotoTypeData, HoverResult}, - inlay_hints::{InlayHint, InlayHintsConfig, InlayKind, LifetimeElisionHints, ReborrowHints}, + inlay_hints::{ + InlayHint, InlayHintsConfig, InlayKind, LifetimeElisionHints, RangeOrOffset, ReborrowHints, + }, join_lines::JoinLinesConfig, markup::Markup, moniker::{MonikerKind, MonikerResult, PackageInformation}, diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 95a6f4f1945d..510b37bb6f63 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs @@ -1360,46 +1360,34 @@ pub(crate) fn handle_inlay_hints_resolve( mut hint: InlayHint, ) -> Result { let _p = profile::span("handle_inlay_hints_resolve"); - let succ = (|| { - let data = match hint.data.take() { - Some(it) => it, - None => return Ok(None), - }; + let data = match hint.data.take() { + Some(it) => it, + 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( - &snap, - resolve_data.position.text_document, - Range::new(resolve_data.position.position, resolve_data.position.position), - )?; - let info = match snap.analysis.hover(&snap.config.hover(), file_range)? { - None => return Ok(None), - Some(info) => info, - }; + let file_range = from_proto::file_range( + &snap, + resolve_data.text_document, + 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)? { + None => return Ok(hint), + Some(info) => info, + }; - let markup_kind = - snap.config.hover().documentation.map_or(ide::HoverDocFormat::Markdown, |kind| kind); - - // FIXME: hover actions? - hint.tooltip = Some(lsp_types::InlayHintTooltip::MarkupContent(to_proto::markup_content( - info.info.markup, - 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(), - })); - } - } + let markup_kind = + snap.config.hover().documentation.map_or(ide::HoverDocFormat::Markdown, |kind| kind); + // FIXME: hover actions? + hint.tooltip = Some(lsp_types::InlayHintTooltip::MarkupContent(to_proto::markup_content( + info.info.markup, + markup_kind, + ))); Ok(hint) } diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs index 8e7e2e236429..c1b230bd9dff 100644 --- a/crates/rust-analyzer/src/lsp_ext.rs +++ b/crates/rust-analyzer/src/lsp_ext.rs @@ -520,7 +520,8 @@ pub struct CompletionResolveData { #[derive(Debug, Serialize, Deserialize)] pub struct InlayHintResolveData { - pub position: lsp_types::TextDocumentPositionParams, + pub text_document: TextDocumentIdentifier, + pub position: PositionOrRange, } #[derive(Debug, Serialize, Deserialize)] diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 9287d7c53e3c..6817090a8bc3 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs @@ -432,11 +432,11 @@ pub(crate) fn inlay_hint( | InlayKind::ChainingHint | InlayKind::GenericParamListHint | 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 { InlayKind::TypeHint => !render_colons, - InlayKind::ChainingHint | InlayKind::ClosingBraceHint(_) => true, + InlayKind::ChainingHint | InlayKind::ClosingBraceHint => true, InlayKind::BindingModeHint | InlayKind::ClosureReturnTypeHint | InlayKind::GenericParamListHint @@ -450,7 +450,7 @@ pub(crate) fn inlay_hint( | InlayKind::GenericParamListHint | InlayKind::ImplicitReborrowHint | InlayKind::TypeHint - | InlayKind::ClosingBraceHint(_) => false, + | InlayKind::ClosingBraceHint => false, InlayKind::BindingModeHint => inlay_hint.label != "&", InlayKind::ParameterHint | InlayKind::LifetimeHint => true, }), @@ -458,7 +458,7 @@ pub(crate) fn inlay_hint( InlayKind::ParameterHint if render_colons => format!("{}:", inlay_hint.label), InlayKind::TypeHint if render_colons => format!(": {}", inlay_hint.label), InlayKind::ClosureReturnTypeHint => format!(" -> {}", inlay_hint.label), - _ => inlay_hint.label, + _ => inlay_hint.label.clone(), }), kind: match inlay_hint.kind { InlayKind::ParameterHint => Some(lsp_types::InlayHintKind::PARAMETER), @@ -469,22 +469,24 @@ pub(crate) fn inlay_hint( | InlayKind::GenericParamListHint | InlayKind::LifetimeHint | InlayKind::ImplicitReborrowHint - | InlayKind::ClosingBraceHint(_) => None, + | InlayKind::ClosingBraceHint => None, }, text_edits: None, - tooltip: None, - data: match inlay_hint.kind { - InlayKind::ClosingBraceHint(Some(offset)) => Some( - to_value(lsp_ext::InlayHintResolveData { - position: lsp_types::TextDocumentPositionParams { - text_document: text_document.clone(), - position: position(line_index, offset), - }, - }) - .unwrap(), - ), - _ => None, - }, + tooltip: Some(lsp_types::InlayHintTooltip::String(inlay_hint.label)), + data: inlay_hint.hover_trigger.map(|range_or_offset| { + to_value(lsp_ext::InlayHintResolveData { + text_document: text_document.clone(), + 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() + }), } } From 0c488fa21502d76b5796a5f9c0f9734b6ad89897 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 17 May 2022 14:48:28 +0200 Subject: [PATCH 5/6] Update lsp-extensions hash --- docs/dev/lsp-extensions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md index 2e1cee8955d1..875561608dc0 100644 --- a/docs/dev/lsp-extensions.md +++ b/docs/dev/lsp-extensions.md @@ -1,5 +1,5 @@