diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs index 5cb67fb95b..0c3e25ce67 100644 --- a/crates/ra_ide_api/src/display/navigation_target.rs +++ b/crates/ra_ide_api/src/display/navigation_target.rs @@ -29,6 +29,20 @@ pub struct NavigationTarget { docs: Option, } +fn find_range_from_node( + db: &RootDatabase, + src: hir::HirFileId, + node: &SyntaxNode, +) -> (FileId, TextRange) { + let text_range = node.text_range(); + let (file_id, text_range) = src + .parent_expansion(db) + .and_then(|(files, expansion_info)| expansion_info.find_range(text_range, files)) + .unwrap_or((src, text_range)); + + (file_id.original_file(db), text_range) +} + impl NavigationTarget { /// When `focus_range` is specified, returns it. otherwise /// returns `full_range` @@ -72,8 +86,12 @@ impl NavigationTarget { self.focus_range } - pub(crate) fn from_bind_pat(file_id: FileId, pat: &ast::BindPat) -> NavigationTarget { - NavigationTarget::from_named(file_id, pat, None, None) + pub(crate) fn from_bind_pat( + db: &RootDatabase, + file_id: FileId, + pat: &ast::BindPat, + ) -> NavigationTarget { + NavigationTarget::from_named(db, file_id.into(), pat, None, None) } pub(crate) fn from_symbol(db: &RootDatabase, symbol: FileSymbol) -> NavigationTarget { @@ -96,7 +114,7 @@ impl NavigationTarget { ) -> NavigationTarget { let parse = db.parse(file_id); let pat = pat.to_node(parse.tree().syntax()); - NavigationTarget::from_bind_pat(file_id, &pat) + NavigationTarget::from_bind_pat(db, file_id, &pat) } pub(crate) fn from_self_param( @@ -119,31 +137,47 @@ impl NavigationTarget { pub(crate) fn from_module(db: &RootDatabase, module: hir::Module) -> NavigationTarget { let src = module.definition_source(db); - let file_id = src.file_id.original_file(db); let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default(); + match src.ast { ModuleSource::SourceFile(node) => { - NavigationTarget::from_syntax(file_id, name, None, node.syntax(), None, None) + let (file_id, text_range) = find_range_from_node(db, src.file_id, node.syntax()); + + NavigationTarget::from_syntax( + file_id, + name, + None, + text_range, + node.syntax(), + None, + None, + ) + } + ModuleSource::Module(node) => { + let (file_id, text_range) = find_range_from_node(db, src.file_id, node.syntax()); + + NavigationTarget::from_syntax( + file_id, + name, + None, + text_range, + node.syntax(), + node.doc_comment_text(), + node.short_label(), + ) } - ModuleSource::Module(node) => NavigationTarget::from_syntax( - file_id, - name, - None, - node.syntax(), - node.doc_comment_text(), - node.short_label(), - ), } } pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget { let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default(); if let Some(src) = module.declaration_source(db) { - let file_id = src.file_id.original_file(db); + let (file_id, text_range) = find_range_from_node(db, src.file_id, src.ast.syntax()); return NavigationTarget::from_syntax( file_id, name, None, + text_range, src.ast.syntax(), src.ast.doc_comment_text(), src.ast.short_label(), @@ -154,13 +188,25 @@ impl NavigationTarget { pub(crate) fn from_field(db: &RootDatabase, field: hir::StructField) -> NavigationTarget { let src = field.source(db); - let file_id = src.file_id.original_file(db); match src.ast { - FieldSource::Named(it) => { - NavigationTarget::from_named(file_id, &it, it.doc_comment_text(), it.short_label()) - } + FieldSource::Named(it) => NavigationTarget::from_named( + db, + src.file_id, + &it, + it.doc_comment_text(), + it.short_label(), + ), FieldSource::Pos(it) => { - NavigationTarget::from_syntax(file_id, "".into(), None, it.syntax(), None, None) + let (file_id, text_range) = find_range_from_node(db, src.file_id, it.syntax()); + NavigationTarget::from_syntax( + file_id, + "".into(), + None, + text_range, + it.syntax(), + None, + None, + ) } } } @@ -172,7 +218,8 @@ impl NavigationTarget { { let src = def.source(db); NavigationTarget::from_named( - src.file_id.original_file(db), + db, + src.file_id, &src.ast, src.ast.doc_comment_text(), src.ast.short_label(), @@ -212,10 +259,13 @@ impl NavigationTarget { impl_block: hir::ImplBlock, ) -> NavigationTarget { let src = impl_block.source(db); + let (file_id, text_range) = find_range_from_node(db, src.file_id, src.ast.syntax()); + NavigationTarget::from_syntax( - src.file_id.original_file(db), + file_id, "impl".into(), None, + text_range, src.ast.syntax(), None, None, @@ -236,12 +286,7 @@ impl NavigationTarget { pub(crate) fn from_macro_def(db: &RootDatabase, macro_call: hir::MacroDef) -> NavigationTarget { let src = macro_call.source(db); log::debug!("nav target {:#?}", src.ast.syntax()); - NavigationTarget::from_named( - src.file_id.original_file(db), - &src.ast, - src.ast.doc_comment_text(), - None, - ) + NavigationTarget::from_named(db, src.file_id, &src.ast, src.ast.doc_comment_text(), None) } #[cfg(test)] @@ -270,21 +315,35 @@ impl NavigationTarget { /// Allows `NavigationTarget` to be created from a `NameOwner` pub(crate) fn from_named( - file_id: FileId, + db: &RootDatabase, + file_id: hir::HirFileId, node: &impl ast::NameOwner, docs: Option, description: Option, ) -> NavigationTarget { //FIXME: use `_` instead of empty string let name = node.name().map(|it| it.text().clone()).unwrap_or_default(); - let focus_range = node.name().map(|it| it.syntax().text_range()); - NavigationTarget::from_syntax(file_id, name, focus_range, node.syntax(), docs, description) + + let focus_range = node.name().map(|it| find_range_from_node(db, file_id, it.syntax()).1); + + let (file_id, full_range) = find_range_from_node(db, file_id, node.syntax()); + + NavigationTarget::from_syntax( + file_id, + name, + focus_range, + full_range, + node.syntax(), + docs, + description, + ) } fn from_syntax( file_id: FileId, name: SmolStr, focus_range: Option, + full_range: TextRange, node: &SyntaxNode, docs: Option, description: Option, @@ -293,9 +352,8 @@ impl NavigationTarget { file_id, name, kind: node.kind(), - full_range: node.text_range(), + full_range, focus_range, - // ptr: Some(LocalSyntaxPtr::new(node)), container_name: None, description, docs, diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index c1ce54bea3..97127706f3 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -101,19 +101,20 @@ pub(crate) fn name_definition( } } - if let Some(nav) = named_target(file_id, &parent) { + if let Some(nav) = named_target(db, file_id, &parent) { return Some(vec![nav]); } None } -fn named_target(file_id: FileId, node: &SyntaxNode) -> Option { +fn named_target(db: &RootDatabase, file_id: FileId, node: &SyntaxNode) -> Option { match_ast! { match node { ast::StructDef(it) => { Some(NavigationTarget::from_named( - file_id, + db, + file_id.into(), &it, it.doc_comment_text(), it.short_label(), @@ -121,7 +122,8 @@ fn named_target(file_id: FileId, node: &SyntaxNode) -> Option }, ast::EnumDef(it) => { Some(NavigationTarget::from_named( - file_id, + db, + file_id.into(), &it, it.doc_comment_text(), it.short_label(), @@ -129,7 +131,8 @@ fn named_target(file_id: FileId, node: &SyntaxNode) -> Option }, ast::EnumVariant(it) => { Some(NavigationTarget::from_named( - file_id, + db, + file_id.into(), &it, it.doc_comment_text(), it.short_label(), @@ -137,7 +140,8 @@ fn named_target(file_id: FileId, node: &SyntaxNode) -> Option }, ast::FnDef(it) => { Some(NavigationTarget::from_named( - file_id, + db, + file_id.into(), &it, it.doc_comment_text(), it.short_label(), @@ -145,7 +149,8 @@ fn named_target(file_id: FileId, node: &SyntaxNode) -> Option }, ast::TypeAliasDef(it) => { Some(NavigationTarget::from_named( - file_id, + db, + file_id.into(), &it, it.doc_comment_text(), it.short_label(), @@ -153,7 +158,8 @@ fn named_target(file_id: FileId, node: &SyntaxNode) -> Option }, ast::ConstDef(it) => { Some(NavigationTarget::from_named( - file_id, + db, + file_id.into(), &it, it.doc_comment_text(), it.short_label(), @@ -161,7 +167,8 @@ fn named_target(file_id: FileId, node: &SyntaxNode) -> Option }, ast::StaticDef(it) => { Some(NavigationTarget::from_named( - file_id, + db, + file_id.into(), &it, it.doc_comment_text(), it.short_label(), @@ -169,7 +176,8 @@ fn named_target(file_id: FileId, node: &SyntaxNode) -> Option }, ast::TraitDef(it) => { Some(NavigationTarget::from_named( - file_id, + db, + file_id.into(), &it, it.doc_comment_text(), it.short_label(), @@ -177,7 +185,8 @@ fn named_target(file_id: FileId, node: &SyntaxNode) -> Option }, ast::RecordFieldDef(it) => { Some(NavigationTarget::from_named( - file_id, + db, + file_id.into(), &it, it.doc_comment_text(), it.short_label(), @@ -185,7 +194,8 @@ fn named_target(file_id: FileId, node: &SyntaxNode) -> Option }, ast::Module(it) => { Some(NavigationTarget::from_named( - file_id, + db, + file_id.into(), &it, it.doc_comment_text(), it.short_label(), @@ -193,7 +203,8 @@ fn named_target(file_id: FileId, node: &SyntaxNode) -> Option }, ast::MacroCall(it) => { Some(NavigationTarget::from_named( - file_id, + db, + file_id.into(), &it, it.doc_comment_text(), None,