3 defs::{Definition, NameClass, NameRefClass},
6 use syntax::{ast, match_ast, AstNode, SyntaxKind::*, T};
8 use crate::{FilePosition, NavigationTarget, RangeInfo};
10 // Feature: Go to Declaration
12 // Navigates to the declaration of an identifier.
13 pub(crate) fn goto_declaration(
15 position: FilePosition,
16 ) -> Option<RangeInfo<Vec<NavigationTarget>>> {
17 let sema = Semantics::new(db);
18 let file = sema.parse(position.file_id).syntax().clone();
19 let original_token = file
20 .token_at_offset(position.offset)
21 .find(|it| matches!(it.kind(), IDENT | T![self] | T![super] | T![crate]))?;
22 let token = sema.descend_into_macros(original_token.clone());
23 let parent = token.parent()?;
24 let def = match_ast! {
26 ast::NameRef(name_ref) => {
27 let name_kind = NameRefClass::classify(&sema, &name_ref)?;
28 name_kind.referenced_local()
31 NameClass::classify(&sema, &name)?.defined_or_referenced_local()
37 Definition::ModuleDef(hir::ModuleDef::Module(module)) => Some(RangeInfo::new(
38 original_token.text_range(),
39 vec![NavigationTarget::from_module_to_decl(db, module)],
47 use ide_db::base_db::FileRange;
51 fn check(ra_fixture: &str) {
52 let (analysis, position, expected) = fixture::nav_target_annotation(ra_fixture);
53 let mut navs = analysis
54 .goto_declaration(position)
56 .expect("no declaration or definition found")
59 panic!("unresolved reference")
61 assert_eq!(navs.len(), 1);
63 let nav = navs.pop().unwrap();
64 assert_eq!(expected, FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() });
68 fn goto_decl_module_outline() {
81 fn goto_decl_module_inline() {