2307: Support hover through macro r=matklad a=kjeremy

Allows hover to work through macros like `match_ast!`.

Co-authored-by: kjeremy <kjeremy@gmail.com>
This commit is contained in:
bors[bot] 2019-11-18 19:57:06 +00:00 committed by GitHub
commit c8fb5b491a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,11 +1,11 @@
//! FIXME: write short doc here //! FIXME: write short doc here
use hir::{Adt, HasSource, HirDisplay, Source}; use hir::{db::AstDatabase, Adt, HasSource, HirDisplay};
use ra_db::SourceDatabase; use ra_db::SourceDatabase;
use ra_syntax::{ use ra_syntax::{
algo::{ancestors_at_offset, find_covering_element, find_node_at_offset}, algo::find_covering_element,
ast::{self, DocCommentsOwner}, ast::{self, DocCommentsOwner},
AstNode, match_ast, AstNode,
}; };
use crate::{ use crate::{
@ -14,6 +14,7 @@ use crate::{
description_from_symbol, docs_from_symbol, macro_label, rust_code_markup, description_from_symbol, docs_from_symbol, macro_label, rust_code_markup,
rust_code_markup_with_doc, ShortLabel, rust_code_markup_with_doc, ShortLabel,
}, },
expand::descend_into_macros,
references::{classify_name, classify_name_ref, NameKind, NameKind::*}, references::{classify_name, classify_name_ref, NameKind, NameKind::*},
FilePosition, FileRange, RangeInfo, FilePosition, FileRange, RangeInfo,
}; };
@ -162,17 +163,18 @@ fn hover_text_from_name_kind(
} }
pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeInfo<HoverResult>> { pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeInfo<HoverResult>> {
let parse = db.parse(position.file_id); let file = db.parse_or_expand(position.file_id.into())?;
let file = parse.tree(); let token = file.token_at_offset(position.offset).filter(|it| !it.kind().is_trivia()).next()?;
let token = descend_into_macros(db, position.file_id, token);
let mut res = HoverResult::new(); let mut res = HoverResult::new();
let mut range = if let Some(name_ref) = let mut range = match_ast! {
find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) match (token.ast.parent()) {
{ ast::NameRef(name_ref) => {
let mut no_fallback = false; let mut no_fallback = false;
if let Some(name_kind) = if let Some(name_kind) =
classify_name_ref(db, Source::new(position.file_id.into(), &name_ref)).map(|d| d.kind) classify_name_ref(db, token.with_ast(&name_ref)).map(|d| d.kind)
{ {
res.extend(hover_text_from_name_kind(db, name_kind, &mut no_fallback)) res.extend(hover_text_from_name_kind(db, name_kind, &mut no_fallback))
} }
@ -192,12 +194,10 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
} else { } else {
None None
} }
} else if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), position.offset) { },
if let Some(name_kind) = ast::Name(name) => {
classify_name(db, Source::new(position.file_id.into(), &name)).map(|d| d.kind) if let Some(name_kind) = classify_name(db, token.with_ast(&name)).map(|d| d.kind) {
{ res.extend(hover_text_from_name_kind(db, name_kind, &mut true));
let mut _b: bool = true;
res.extend(hover_text_from_name_kind(db, name_kind, &mut _b));
} }
if !res.is_empty() { if !res.is_empty() {
@ -205,12 +205,13 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
} else { } else {
None None
} }
} else { },
None _ => None,
}
}; };
if range.is_none() { if range.is_none() {
let node = ancestors_at_offset(file.syntax(), position.offset).find(|n| { let node = token.ast.ancestors().find(|n| {
ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some() ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some()
})?; })?;
let frange = FileRange { file_id: position.file_id, range: node.text_range() }; let frange = FileRange { file_id: position.file_id, range: node.text_range() };
@ -716,4 +717,23 @@ fn func(foo: i32) { if true { <|>foo; }; }
assert_eq!(trim_markup_opt(hover.info.first()), Some("i32")); assert_eq!(trim_markup_opt(hover.info.first()), Some("i32"));
assert_eq!(hover.info.is_exact(), true); assert_eq!(hover.info.is_exact(), true);
} }
#[test]
fn test_hover_through_macro() {
check_hover_result(
"
//- /lib.rs
macro_rules! id {
($($tt:tt)*) => { $($tt)* }
}
fn foo() {}
id! {
fn bar() {
fo<|>o();
}
}
",
&["fn foo()"],
);
}
} }