]> git.lizzy.rs Git - rust.git/commitdiff
Trigger hover requests on closing brace hints
authorLukas Wirth <lukastw97@gmail.com>
Tue, 17 May 2022 11:39:45 +0000 (13:39 +0200)
committerLukas Wirth <lukastw97@gmail.com>
Tue, 17 May 2022 11:39:45 +0000 (13:39 +0200)
crates/ide/src/inlay_hints.rs
crates/rust-analyzer/src/handlers.rs
crates/rust-analyzer/src/lsp_ext.rs
crates/rust-analyzer/src/to_proto.rs

index 343a8f7acce3c04709a8f6cdb80e6f1dda51f634..4684f92ae8d47a8f02bcce71cc3bfddb1afab0b4 100644 (file)
@@ -8,7 +8,8 @@
 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<TextSize>),
     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,
     });
 
index e832f4b45a0c2326d37a6ea6c8b8e235c4f8319c..95a6f4f1945d864d76e7b962b63bb5b3e7b53b7f 100644 (file)
@@ -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,
+                    &params.text_document,
+                    inlay_hints_config.render_colons,
+                    it,
+                )
+            })
             .collect(),
     ))
 }
 
 pub(crate) fn handle_inlay_hints_resolve(
-    _snap: GlobalStateSnapshot,
+    snap: GlobalStateSnapshot,
     mut hint: InlayHint,
 ) -> Result<InlayHint> {
-    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)
 }
 
index 1cfaa1332742ddd84e44328bd29c390af9ff398b..8e7e2e2364291c55084c3a6a34c737b036fa40f8 100644 (file)
@@ -518,6 +518,11 @@ pub struct CompletionResolveData {
     pub imports: Vec<CompletionImport>,
 }
 
+#[derive(Debug, Serialize, Deserialize)]
+pub struct InlayHintResolveData {
+    pub position: lsp_types::TextDocumentPositionParams,
+}
+
 #[derive(Debug, Serialize, Deserialize)]
 pub struct CompletionImport {
     pub full_import_path: String,
index 83d863ce36b818f8ac15af5130e08eea9c0fe712..9287d7c53e3c8d6ee7cb1bf50a5b89c953386d34 100644 (file)
@@ -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,
+        },
     }
 }