From fd52d721e1ed9794048d63e546f43805d24d7ab8 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 17 Nov 2019 20:15:55 +0300 Subject: More correct expansion mapping We can't really map arbitrary ranges, we only can map tokens --- crates/ra_ide_api/src/goto_definition.rs | 48 +++++++++++++++++--------------- 1 file changed, 26 insertions(+), 22 deletions(-) (limited to 'crates/ra_ide_api/src') diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 70baa294f..b693a4c31 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -4,9 +4,8 @@ use std::iter::successors; use hir::{db::AstDatabase, Source}; use ra_syntax::{ - algo::find_node_at_offset, ast::{self, DocCommentsOwner}, - match_ast, AstNode, SyntaxNode, TextUnit, + match_ast, AstNode, SyntaxNode, SyntaxToken, }; use crate::{ @@ -20,37 +19,42 @@ pub(crate) fn goto_definition( db: &RootDatabase, position: FilePosition, ) -> Option>> { - let offset = descend_into_macros(db, position); + let token = descend_into_macros(db, position)?; - let syntax = db.parse_or_expand(offset.file_id)?; + let res = match_ast! { + match (token.ast.parent()) { + ast::NameRef(name_ref) => { + let navs = reference_definition(db, token.with_ast(&name_ref)).to_vec(); + RangeInfo::new(name_ref.syntax().text_range(), navs.to_vec()) + }, + ast::Name(name) => { + let navs = name_definition(db, token.with_ast(&name))?; + RangeInfo::new(name.syntax().text_range(), navs) - if let Some(name_ref) = find_node_at_offset::(&syntax, offset.ast) { - let navs = reference_definition(db, offset.with_ast(&name_ref)).to_vec(); - return Some(RangeInfo::new(name_ref.syntax().text_range(), navs.to_vec())); - } - if let Some(name) = find_node_at_offset::(&syntax, offset.ast) { - let navs = name_definition(db, offset.with_ast(&name))?; - return Some(RangeInfo::new(name.syntax().text_range(), navs)); - } - None + }, + _ => return None, + } + }; + + Some(res) } -fn descend_into_macros(db: &RootDatabase, position: FilePosition) -> Source { - successors(Some(Source::new(position.file_id.into(), position.offset)), |offset| { - let syntax = db.parse_or_expand(offset.file_id)?; - let macro_call = find_node_at_offset::(&syntax, offset.ast)?; +fn descend_into_macros(db: &RootDatabase, position: FilePosition) -> Option> { + 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()?; + + successors(Some(Source::new(position.file_id.into(), token)), |token| { + let macro_call = token.ast.ancestors().find_map(ast::MacroCall::cast)?; let tt = macro_call.token_tree()?; - if !tt.syntax().text_range().contains(offset.ast) { + if !token.ast.text_range().is_subrange(&tt.syntax().text_range()) { return None; } let source_analyzer = - hir::SourceAnalyzer::new(db, offset.with_ast(macro_call.syntax()), None); + hir::SourceAnalyzer::new(db, token.with_ast(token.ast.parent()).as_ref(), None); let exp = source_analyzer.expand(db, ¯o_call)?; - let next_offset = exp.translate_offset(db, offset.ast)?; - Some(Source::new(exp.file_id(), next_offset)) + exp.map_token_down(db, token.as_ref()) }) .last() - .unwrap() } #[derive(Debug)] -- cgit v1.2.3