From c2a0f5e50f6deb2e15bbfa6056a3cc0866c203a5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 5 Jan 2019 16:20:48 +0300 Subject: move goto_defenition to a separate file --- crates/ra_analysis/src/goto_defenition.rs | 80 +++++++++++++++++++++++++++++++ crates/ra_analysis/src/imp.rs | 2 +- crates/ra_analysis/src/lib.rs | 20 ++++---- 3 files changed, 91 insertions(+), 11 deletions(-) create mode 100644 crates/ra_analysis/src/goto_defenition.rs (limited to 'crates/ra_analysis/src') diff --git a/crates/ra_analysis/src/goto_defenition.rs b/crates/ra_analysis/src/goto_defenition.rs new file mode 100644 index 000000000..91de7ef65 --- /dev/null +++ b/crates/ra_analysis/src/goto_defenition.rs @@ -0,0 +1,80 @@ +use ra_db::{FileId, Cancelable, SyntaxDatabase}; +use ra_syntax::{TextRange, AstNode, ast, SyntaxKind::{NAME, MODULE}}; + +use ra_editor::find_node_at_offset; + +use crate::{FilePosition, NavigationTarget, db::RootDatabase}; + +pub(crate) fn goto_defenition( + db: &RootDatabase, + position: FilePosition, +) -> Cancelable>> { + let file = db.source_file(position.file_id); + let syntax = file.syntax(); + if let Some(name_ref) = find_node_at_offset::(syntax, position.offset) { + return Ok(Some(reference_defenition(db, position.file_id, name_ref)?)); + } + if let Some(name) = find_node_at_offset::(syntax, position.offset) { + return name_defenition(db, position.file_id, name); + } + Ok(None) +} + +fn reference_defenition( + db: &RootDatabase, + file_id: FileId, + name_ref: ast::NameRef, +) -> Cancelable> { + if let Some(fn_descr) = + hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax())? + { + let scope = fn_descr.scopes(db); + // First try to resolve the symbol locally + if let Some(entry) = scope.resolve_local_name(name_ref) { + let nav = NavigationTarget { + file_id, + name: entry.name().to_string().into(), + range: entry.ptr().range(), + kind: NAME, + ptr: None, + }; + return Ok(vec![nav]); + }; + } + // If that fails try the index based approach. + let navs = db + .index_resolve(name_ref)? + .into_iter() + .map(NavigationTarget::from_symbol) + .collect(); + Ok(navs) +} + +fn name_defenition( + db: &RootDatabase, + file_id: FileId, + name: ast::Name, +) -> Cancelable>> { + if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { + if module.has_semi() { + if let Some(child_module) = + hir::source_binder::module_from_declaration(db, file_id, module)? + { + let file_id = child_module.file_id(); + let name = match child_module.name() { + Some(name) => name.to_string().into(), + None => "".into(), + }; + let nav = NavigationTarget { + file_id, + name, + range: TextRange::offset_len(0.into(), 0.into()), + kind: MODULE, + ptr: None, + }; + return Ok(Some(vec![nav])); + } + } + } + Ok(None) +} diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index e2871451c..6df118c20 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs @@ -416,7 +416,7 @@ impl db::RootDatabase { .collect::>(); Ok(res) } - fn index_resolve(&self, name_ref: ast::NameRef) -> Cancelable> { + pub(crate) fn index_resolve(&self, name_ref: ast::NameRef) -> Cancelable> { let name = name_ref.text(); let mut query = Query::new(name.to_string()); query.exact(); diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 70ee448fc..0dac9f268 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs @@ -15,6 +15,7 @@ macro_rules! ctry { mod db; mod imp; mod completion; +mod goto_defenition; mod symbol_index; pub mod mock_analysis; mod runnables; @@ -396,16 +397,15 @@ impl Analysis { &self, position: FilePosition, ) -> Cancelable>> { - let r = self.approximately_resolve_symbol(position)?; - Ok(r.map(|it| it.resolves_to)) - } - /// Resolves reference to definition, but does not gurantee correctness. - pub fn approximately_resolve_symbol( - &self, - position: FilePosition, - ) -> Cancelable> { - self.db.approximately_resolve_symbol(position) - } + goto_defenition::goto_defenition(&*self.db, position) + } + // /// Resolves reference to definition, but does not gurantee correctness. + // pub fn approximately_resolve_symbol( + // &self, + // position: FilePosition, + // ) -> Cancelable> { + // self.db.approximately_resolve_symbol(position) + // } /// Finds all usages of the reference at point. pub fn find_all_refs(&self, position: FilePosition) -> Cancelable> { self.db.find_all_refs(position) -- cgit v1.2.3