show types in local variable hovers

This commit is contained in:
Aleksey Kladov 2019-01-05 20:53:30 +03:00
parent ee461a2111
commit be84a112a7
2 changed files with 27 additions and 10 deletions

View file

@ -14,23 +14,28 @@ pub(crate) fn hover(
) -> Cancelable<Option<RangeInfo<String>>> { ) -> Cancelable<Option<RangeInfo<String>>> {
let file = db.source_file(position.file_id); let file = db.source_file(position.file_id);
let mut res = Vec::new(); let mut res = Vec::new();
let range = if let Some(name_ref) =
find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) let mut range = None;
{ if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) {
let navs = crate::goto_defenition::reference_defenition(db, position.file_id, name_ref)?; let navs = crate::goto_defenition::reference_defenition(db, position.file_id, name_ref)?;
for nav in navs { for nav in navs {
res.extend(doc_text_for(db, nav)?) res.extend(doc_text_for(db, nav)?)
} }
name_ref.syntax().range() if !res.is_empty() {
} else { range = Some(name_ref.syntax().range())
}
}
if range.is_none() {
let expr: ast::Expr = ctry!(find_node_at_offset(file.syntax(), position.offset)); let expr: ast::Expr = ctry!(find_node_at_offset(file.syntax(), position.offset));
let frange = FileRange { let frange = FileRange {
file_id: position.file_id, file_id: position.file_id,
range: expr.syntax().range(), range: expr.syntax().range(),
}; };
res.extend(type_of(db, frange)?); res.extend(type_of(db, frange)?);
expr.syntax().range() range = Some(expr.syntax().range());
}; };
let range = ctry!(range);
if res.is_empty() { if res.is_empty() {
return Ok(None); return Ok(None);
} }
@ -41,7 +46,13 @@ pub(crate) fn hover(
pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Cancelable<Option<String>> { pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Cancelable<Option<String>> {
let file = db.source_file(frange.file_id); let file = db.source_file(frange.file_id);
let syntax = file.syntax(); let syntax = file.syntax();
let node = find_covering_node(syntax, frange.range); let leaf_node = find_covering_node(syntax, frange.range);
// if we picked identifier, expand to pattern/expression
let node = leaf_node
.ancestors()
.take_while(|it| it.range() == leaf_node.range())
.find(|&it| ast::Expr::cast(it).is_some() || ast::Pat::cast(it).is_some())
.unwrap_or(leaf_node);
let parent_fn = ctry!(node.ancestors().find_map(ast::FnDef::cast)); let parent_fn = ctry!(node.ancestors().find_map(ast::FnDef::cast));
let function = ctry!(hir::source_binder::function_from_source( let function = ctry!(hir::source_binder::function_from_source(
db, db,
@ -156,7 +167,6 @@ impl NavigationTarget {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use ra_syntax::TextRange; use ra_syntax::TextRange;
use crate::mock_analysis::single_file_with_position; use crate::mock_analysis::single_file_with_position;
#[test] #[test]
@ -174,4 +184,11 @@ mod tests {
assert_eq!(hover.range, TextRange::from_to(95.into(), 100.into())); assert_eq!(hover.range, TextRange::from_to(95.into(), 100.into()));
assert_eq!(hover.info, "u32"); assert_eq!(hover.info, "u32");
} }
#[test]
fn hover_for_local_variable() {
let (analysis, position) = single_file_with_position("fn func(foo: i32) { fo<|>o; }");
let hover = analysis.hover(position).unwrap().unwrap();
assert_eq!(hover.info, "i32");
}
} }

View file

@ -228,7 +228,7 @@ impl Query {
/// ///
/// Typically, a `NavigationTarget` corresponds to some element in the source /// Typically, a `NavigationTarget` corresponds to some element in the source
/// code, like a function or a struct, but this is not strictly required. /// code, like a function or a struct, but this is not strictly required.
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct NavigationTarget { pub struct NavigationTarget {
file_id: FileId, file_id: FileId,
name: SmolStr, name: SmolStr,