Goto type def through macros

This commit is contained in:
kjeremy 2019-11-18 14:57:42 -05:00
parent 7614439033
commit e939f740b3

View file

@ -1,25 +1,28 @@
//! FIXME: write short doc here
use ra_db::SourceDatabase;
use hir::db::AstDatabase;
use ra_syntax::{ast, AstNode};
use crate::{db::RootDatabase, display::ToNav, FilePosition, NavigationTarget, RangeInfo};
use crate::{
db::RootDatabase, display::ToNav, expand::descend_into_macros, FilePosition, NavigationTarget,
RangeInfo,
};
pub(crate) fn goto_type_definition(
db: &RootDatabase,
position: FilePosition,
) -> Option<RangeInfo<Vec<NavigationTarget>>> {
let parse = db.parse(position.file_id);
let file = db.parse_or_expand(position.file_id.into())?;
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 node = parse.tree().syntax().token_at_offset(position.offset).find_map(|token| {
let node = token.ast.ancestors().find_map(|token| {
token
.parent()
.ancestors()
.find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some())
})?;
let analyzer =
hir::SourceAnalyzer::new(db, hir::Source::new(position.file_id.into(), &node), None);
let analyzer = hir::SourceAnalyzer::new(db, token.with_ast(&node), None);
let ty: hir::Ty = if let Some(ty) =
ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e))
@ -80,4 +83,23 @@ mod tests {
"Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)",
);
}
#[test]
fn goto_type_definition_works_through_macro() {
check_goto(
"
//- /lib.rs
macro_rules! id {
($($tt:tt)*) => { $($tt)* }
}
struct Foo {}
id! {
fn bar() {
let f<|> = Foo {};
}
}
",
"Foo STRUCT_DEF FileId(1) [52; 65) [59; 62)",
);
}
}