From 8ca3bb8fcd3c3ac8eb232086f6286eb96f4bac79 Mon Sep 17 00:00:00 2001 From: Alexander Gonzalez Date: Sat, 24 Jul 2021 21:54:48 -0400 Subject: [PATCH] feat: Add the hover_range capability --- crates/ide/src/hover.rs | 28 +++++++++++++++++++++++++--- crates/rust-analyzer/src/handlers.rs | 7 ++++--- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index afa67f72bed..692c3ff676a 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -1,7 +1,7 @@ use either::Either; use hir::{AsAssocItem, HasAttrs, HasSource, HirDisplay, Semantics}; use ide_db::{ - base_db::SourceDatabase, + base_db::{FileRange, SourceDatabase}, defs::{Definition, NameClass, NameRefClass}, helpers::{ generated_lints::{CLIPPY_LINTS, DEFAULT_LINTS, FEATURES}, @@ -12,8 +12,12 @@ use itertools::Itertools; use stdx::format_to; use syntax::{ - algo, ast, display::fn_as_proc_macro_label, match_ast, AstNode, AstToken, Direction, - SyntaxKind::*, SyntaxToken, T, + algo::{self, find_node_at_range}, + ast, + display::fn_as_proc_macro_label, + match_ast, AstNode, AstToken, Direction, + SyntaxKind::*, + SyntaxToken, T, }; use crate::{ @@ -246,6 +250,24 @@ pub(crate) fn hover_range( range: FileRange, config: &HoverConfig, ) -> Option> { + let sema = hir::Semantics::new(db); + let file = sema.parse(range.file_id).syntax().clone(); + let expr = find_node_at_range::(&file, range.range)?; + let ty = sema.type_of_expr(&expr)?; + + if ty.is_unknown() { + return None; + } + + let mut res = HoverResult::default(); + + res.markup = if config.markdown() { + Markup::fenced_block(&ty.display(db)) + } else { + ty.display(db).to_string().into() + }; + + Some(RangeInfo::new(range.range, res)) } fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option { diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index ede3103abfa..6fae4b04a40 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs @@ -873,24 +873,25 @@ pub(crate) fn handle_hover( let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let range = from_proto::file_range(&snap, params.text_document, params.range)?; - let info = if range.end - range.start == 1 { + let info = if range.range.is_empty() { // It's a hover over a position match snap .analysis - .hover(&snap.config.hover(), FilePosition { file_id, offset: range.start })? + .hover(&snap.config.hover(), FilePosition { file_id, offset: range.range.start() })? { None => return Ok(None), Some(info) => info, } } else { // It's a hover over a range + log::info!("Triggered range hover"); match snap.analysis.hover_range(&snap.config.hover(), range)? { None => return Ok(None), Some(info) => info, } }; - let line_index = snap.file_line_index(position.file_id)?; + let line_index = snap.file_line_index(range.file_id)?; let range = to_proto::range(&line_index, info.range); let hover = lsp_ext::Hover { hover: lsp_types::Hover {