feat: Add the hover_range capability

This commit is contained in:
Alexander Gonzalez 2021-07-24 21:54:48 -04:00
parent 20c64cc0e6
commit 8ca3bb8fcd
2 changed files with 29 additions and 6 deletions

View File

@ -1,7 +1,7 @@
use either::Either; use either::Either;
use hir::{AsAssocItem, HasAttrs, HasSource, HirDisplay, Semantics}; use hir::{AsAssocItem, HasAttrs, HasSource, HirDisplay, Semantics};
use ide_db::{ use ide_db::{
base_db::SourceDatabase, base_db::{FileRange, SourceDatabase},
defs::{Definition, NameClass, NameRefClass}, defs::{Definition, NameClass, NameRefClass},
helpers::{ helpers::{
generated_lints::{CLIPPY_LINTS, DEFAULT_LINTS, FEATURES}, generated_lints::{CLIPPY_LINTS, DEFAULT_LINTS, FEATURES},
@ -12,8 +12,12 @@
use itertools::Itertools; use itertools::Itertools;
use stdx::format_to; use stdx::format_to;
use syntax::{ use syntax::{
algo, ast, display::fn_as_proc_macro_label, match_ast, AstNode, AstToken, Direction, algo::{self, find_node_at_range},
SyntaxKind::*, SyntaxToken, T, ast,
display::fn_as_proc_macro_label,
match_ast, AstNode, AstToken, Direction,
SyntaxKind::*,
SyntaxToken, T,
}; };
use crate::{ use crate::{
@ -246,6 +250,24 @@ pub(crate) fn hover_range(
range: FileRange, range: FileRange,
config: &HoverConfig, config: &HoverConfig,
) -> Option<RangeInfo<HoverResult>> { ) -> Option<RangeInfo<HoverResult>> {
let sema = hir::Semantics::new(db);
let file = sema.parse(range.file_id).syntax().clone();
let expr = find_node_at_range::<ast::Expr>(&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<HoverAction> { fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {

View File

@ -873,24 +873,25 @@ pub(crate) fn handle_hover(
let file_id = from_proto::file_id(&snap, &params.text_document.uri)?; let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
let range = from_proto::file_range(&snap, params.text_document, params.range)?; 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 // It's a hover over a position
match snap match snap
.analysis .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), None => return Ok(None),
Some(info) => info, Some(info) => info,
} }
} else { } else {
// It's a hover over a range // It's a hover over a range
log::info!("Triggered range hover");
match snap.analysis.hover_range(&snap.config.hover(), range)? { match snap.analysis.hover_range(&snap.config.hover(), range)? {
None => return Ok(None), None => return Ok(None),
Some(info) => info, 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 range = to_proto::range(&line_index, info.range);
let hover = lsp_ext::Hover { let hover = lsp_ext::Hover {
hover: lsp_types::Hover { hover: lsp_types::Hover {