From 4344264024d374bb9cdc6f388f13c90b48c6c22e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 5 Dec 2018 13:16:20 +0300 Subject: move fuzzy source binding to a separete mode --- crates/ra_hir/src/function/mod.rs | 52 +------------------- crates/ra_hir/src/lib.rs | 1 + crates/ra_hir/src/module/mod.rs | 71 ++-------------------------- crates/ra_hir/src/module/nameres.rs | 4 +- crates/ra_hir/src/source_binder.rs | 94 +++++++++++++++++++++++++++++++++++++ 5 files changed, 104 insertions(+), 118 deletions(-) create mode 100644 crates/ra_hir/src/source_binder.rs (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/function/mod.rs b/crates/ra_hir/src/function/mod.rs index e00bca6e3..5187dc051 100644 --- a/crates/ra_hir/src/function/mod.rs +++ b/crates/ra_hir/src/function/mod.rs @@ -6,16 +6,11 @@ use std::{ }; use ra_syntax::{ - TextRange, TextUnit, SyntaxNodeRef, + TextRange, TextUnit, ast::{self, AstNode, DocCommentsOwner, NameOwner}, }; -use ra_db::FileId; -use crate::{ - Cancelable, - DefLoc, DefKind, DefId, HirDatabase, SourceItemId, - Module, -}; +use crate::{ DefId, HirDatabase }; pub use self::scope::FnScopes; @@ -32,49 +27,6 @@ impl Function { Function { fn_id } } - pub fn guess_from_source( - db: &impl HirDatabase, - file_id: FileId, - fn_def: ast::FnDef, - ) -> Cancelable> { - let module = ctry!(Module::guess_from_child_node(db, file_id, fn_def.syntax())?); - let file_items = db.file_items(file_id); - let item_id = file_items.id_of(fn_def.syntax()); - let source_item_id = SourceItemId { file_id, item_id }; - let def_loc = DefLoc { - kind: DefKind::Function, - source_root_id: module.source_root_id, - module_id: module.module_id, - source_item_id, - }; - Ok(Some(Function::new(def_loc.id(db)))) - } - - pub fn guess_for_name_ref( - db: &impl HirDatabase, - file_id: FileId, - name_ref: ast::NameRef, - ) -> Cancelable> { - Function::guess_for_node(db, file_id, name_ref.syntax()) - } - - pub fn guess_for_bind_pat( - db: &impl HirDatabase, - file_id: FileId, - bind_pat: ast::BindPat, - ) -> Cancelable> { - Function::guess_for_node(db, file_id, bind_pat.syntax()) - } - - fn guess_for_node( - db: &impl HirDatabase, - file_id: FileId, - node: SyntaxNodeRef, - ) -> Cancelable> { - let fn_def = ctry!(node.ancestors().find_map(ast::FnDef::cast)); - Function::guess_from_source(db, file_id, fn_def) - } - pub fn scope(&self, db: &impl HirDatabase) -> Arc { db.fn_scopes(self.fn_id) } diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 9168dad3b..983ce99cb 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -22,6 +22,7 @@ mod function; mod module; mod path; mod arena; +pub mod source_binder; use std::ops::Index; diff --git a/crates/ra_hir/src/module/mod.rs b/crates/ra_hir/src/module/mod.rs index 11e6e8e75..9ab7dbff5 100644 --- a/crates/ra_hir/src/module/mod.rs +++ b/crates/ra_hir/src/module/mod.rs @@ -3,14 +3,12 @@ pub(super) mod nameres; use std::sync::Arc; -use ra_editor::find_node_at_offset; - use ra_syntax::{ algo::generate, ast::{self, AstNode, NameOwner}, - SmolStr, SyntaxNode, SyntaxNodeRef, + SmolStr, SyntaxNode, }; -use ra_db::{SourceRootId, FileId, FilePosition, Cancelable}; +use ra_db::{SourceRootId, FileId, Cancelable}; use relative_path::RelativePathBuf; use crate::{ @@ -30,68 +28,6 @@ pub struct Module { } impl Module { - /// Lookup `Module` by `FileId`. Note that this is inherently - /// lossy transformation: in general, a single source might correspond to - /// several modules. - pub fn guess_from_file_id( - db: &impl HirDatabase, - file_id: FileId, - ) -> Cancelable> { - let module_source = ModuleSource::new_file(db, file_id); - Module::guess_from_source(db, module_source) - } - - /// Lookup `Module` by position in the source code. Note that this - /// is inherently lossy transformation: in general, a single source might - /// correspond to several modules. - pub fn guess_from_position( - db: &impl HirDatabase, - position: FilePosition, - ) -> Cancelable> { - let file = db.source_file(position.file_id); - let module_source = match find_node_at_offset::(file.syntax(), position.offset) - { - Some(m) if !m.has_semi() => ModuleSource::new_inline(db, position.file_id, m), - _ => ModuleSource::new_file(db, position.file_id), - }; - Module::guess_from_source(db, module_source) - } - - pub fn guess_from_child_node( - db: &impl HirDatabase, - file_id: FileId, - node: SyntaxNodeRef, - ) -> Cancelable> { - let module_source = if let Some(m) = node - .ancestors() - .filter_map(ast::Module::cast) - .find(|it| !it.has_semi()) - { - ModuleSource::new_inline(db, file_id, m) - } else { - ModuleSource::new_file(db, file_id) - }; - Module::guess_from_source(db, module_source) - } - - fn guess_from_source( - db: &impl HirDatabase, - module_source: ModuleSource, - ) -> Cancelable> { - let source_root_id = db.file_source_root(module_source.file_id()); - let module_tree = db.module_tree(source_root_id)?; - - let res = match module_tree.any_module_for_source(module_source) { - None => None, - Some(module_id) => Some(Module { - tree: module_tree, - source_root_id, - module_id, - }), - }; - Ok(res) - } - pub(super) fn new( db: &impl HirDatabase, source_root_id: SourceRootId, @@ -225,7 +161,8 @@ impl ModuleTree { .collect() } - fn any_module_for_source(&self, source: ModuleSource) -> Option { + //TODO: move to source binders? + pub(crate) fn any_module_for_source(&self, source: ModuleSource) -> Option { self.modules_for_source(source).pop() } } diff --git a/crates/ra_hir/src/module/nameres.rs b/crates/ra_hir/src/module/nameres.rs index c2b380a80..61a1acfe6 100644 --- a/crates/ra_hir/src/module/nameres.rs +++ b/crates/ra_hir/src/module/nameres.rs @@ -363,7 +363,9 @@ mod tests { fn item_map(fixture: &str) -> (Arc, hir::ModuleId) { let (db, pos) = MockDatabase::with_position(fixture); let source_root = db.file_source_root(pos.file_id); - let module = hir::Module::guess_from_position(&db, pos).unwrap().unwrap(); + let module = hir::source_binder::module_from_position(&db, pos) + .unwrap() + .unwrap(); let module_id = module.module_id; (db.item_map(source_root).unwrap(), module_id) } diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs new file mode 100644 index 000000000..dbf0a4de8 --- /dev/null +++ b/crates/ra_hir/src/source_binder.rs @@ -0,0 +1,94 @@ +/// Lookup hir elements using position in the source code. This is a lossy +/// transformation: in general, a single source might correspond to several +/// modules, functions, etc, due to macros, cfgs and `#[path=]` attributes on +/// modules. +/// +/// So, this modules should not be used during hir construction, it exists +/// purely for "IDE needs". +use ra_db::{FileId, FilePosition, Cancelable}; +use ra_editor::find_node_at_offset; +use ra_syntax::{ + ast::{self, AstNode}, + SyntaxNodeRef, +}; + +use crate::{ + HirDatabase, Module, Function, SourceItemId, + module::ModuleSource, + DefKind, DefLoc +}; + +/// Locates the module by `FileId`. Picks topmost module in the file. +pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Cancelable> { + let module_source = ModuleSource::new_file(db, file_id); + module_from_source(db, module_source) +} + +/// Locates the module by position in the source code. +pub fn module_from_position( + db: &impl HirDatabase, + position: FilePosition, +) -> Cancelable> { + let file = db.source_file(position.file_id); + let module_source = match find_node_at_offset::(file.syntax(), position.offset) { + Some(m) if !m.has_semi() => ModuleSource::new_inline(db, position.file_id, m), + _ => ModuleSource::new_file(db, position.file_id), + }; + module_from_source(db, module_source) +} + +/// Locates the module by child syntax element within the module +pub fn module_from_child_node( + db: &impl HirDatabase, + file_id: FileId, + child: SyntaxNodeRef, +) -> Cancelable> { + let module_source = if let Some(m) = child + .ancestors() + .filter_map(ast::Module::cast) + .find(|it| !it.has_semi()) + { + ModuleSource::new_inline(db, file_id, m) + } else { + ModuleSource::new_file(db, file_id) + }; + module_from_source(db, module_source) +} + +fn module_from_source( + db: &impl HirDatabase, + module_source: ModuleSource, +) -> Cancelable> { + let source_root_id = db.file_source_root(module_source.file_id()); + let module_tree = db.module_tree(source_root_id)?; + + let module_id = ctry!(module_tree.any_module_for_source(module_source)); + Ok(Some(Module::new(db, source_root_id, module_id)?)) +} + +pub fn function_from_source( + db: &impl HirDatabase, + file_id: FileId, + fn_def: ast::FnDef, +) -> Cancelable> { + let module = ctry!(module_from_child_node(db, file_id, fn_def.syntax())?); + let file_items = db.file_items(file_id); + let item_id = file_items.id_of(fn_def.syntax()); + let source_item_id = SourceItemId { file_id, item_id }; + let def_loc = DefLoc { + kind: DefKind::Function, + source_root_id: module.source_root_id, + module_id: module.module_id, + source_item_id, + }; + Ok(Some(Function::new(def_loc.id(db)))) +} + +pub fn function_from_child_node( + db: &impl HirDatabase, + file_id: FileId, + node: SyntaxNodeRef, +) -> Cancelable> { + let fn_def = ctry!(node.ancestors().find_map(ast::FnDef::cast)); + function_from_source(db, file_id, fn_def) +} -- cgit v1.2.3