aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-12-05 10:16:20 +0000
committerAleksey Kladov <[email protected]>2018-12-05 10:16:20 +0000
commit4344264024d374bb9cdc6f388f13c90b48c6c22e (patch)
tree52913fe6fe5127d4c4f1d0dd7b412ed0df03245a /crates/ra_hir
parent7960c8b27681ebeb72d83930c4a2bbf43a982c52 (diff)
move fuzzy source binding to a separete mode
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/function/mod.rs52
-rw-r--r--crates/ra_hir/src/lib.rs1
-rw-r--r--crates/ra_hir/src/module/mod.rs71
-rw-r--r--crates/ra_hir/src/module/nameres.rs4
-rw-r--r--crates/ra_hir/src/source_binder.rs94
5 files changed, 104 insertions, 118 deletions
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::{
6}; 6};
7 7
8use ra_syntax::{ 8use ra_syntax::{
9 TextRange, TextUnit, SyntaxNodeRef, 9 TextRange, TextUnit,
10 ast::{self, AstNode, DocCommentsOwner, NameOwner}, 10 ast::{self, AstNode, DocCommentsOwner, NameOwner},
11}; 11};
12use ra_db::FileId;
13 12
14use crate::{ 13use crate::{ DefId, HirDatabase };
15 Cancelable,
16 DefLoc, DefKind, DefId, HirDatabase, SourceItemId,
17 Module,
18};
19 14
20pub use self::scope::FnScopes; 15pub use self::scope::FnScopes;
21 16
@@ -32,49 +27,6 @@ impl Function {
32 Function { fn_id } 27 Function { fn_id }
33 } 28 }
34 29
35 pub fn guess_from_source(
36 db: &impl HirDatabase,
37 file_id: FileId,
38 fn_def: ast::FnDef,
39 ) -> Cancelable<Option<Function>> {
40 let module = ctry!(Module::guess_from_child_node(db, file_id, fn_def.syntax())?);
41 let file_items = db.file_items(file_id);
42 let item_id = file_items.id_of(fn_def.syntax());
43 let source_item_id = SourceItemId { file_id, item_id };
44 let def_loc = DefLoc {
45 kind: DefKind::Function,
46 source_root_id: module.source_root_id,
47 module_id: module.module_id,
48 source_item_id,
49 };
50 Ok(Some(Function::new(def_loc.id(db))))
51 }
52
53 pub fn guess_for_name_ref(
54 db: &impl HirDatabase,
55 file_id: FileId,
56 name_ref: ast::NameRef,
57 ) -> Cancelable<Option<Function>> {
58 Function::guess_for_node(db, file_id, name_ref.syntax())
59 }
60
61 pub fn guess_for_bind_pat(
62 db: &impl HirDatabase,
63 file_id: FileId,
64 bind_pat: ast::BindPat,
65 ) -> Cancelable<Option<Function>> {
66 Function::guess_for_node(db, file_id, bind_pat.syntax())
67 }
68
69 fn guess_for_node(
70 db: &impl HirDatabase,
71 file_id: FileId,
72 node: SyntaxNodeRef,
73 ) -> Cancelable<Option<Function>> {
74 let fn_def = ctry!(node.ancestors().find_map(ast::FnDef::cast));
75 Function::guess_from_source(db, file_id, fn_def)
76 }
77
78 pub fn scope(&self, db: &impl HirDatabase) -> Arc<FnScopes> { 30 pub fn scope(&self, db: &impl HirDatabase) -> Arc<FnScopes> {
79 db.fn_scopes(self.fn_id) 31 db.fn_scopes(self.fn_id)
80 } 32 }
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;
22mod module; 22mod module;
23mod path; 23mod path;
24mod arena; 24mod arena;
25pub mod source_binder;
25 26
26use std::ops::Index; 27use std::ops::Index;
27 28
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;
3 3
4use std::sync::Arc; 4use std::sync::Arc;
5 5
6use ra_editor::find_node_at_offset;
7
8use ra_syntax::{ 6use ra_syntax::{
9 algo::generate, 7 algo::generate,
10 ast::{self, AstNode, NameOwner}, 8 ast::{self, AstNode, NameOwner},
11 SmolStr, SyntaxNode, SyntaxNodeRef, 9 SmolStr, SyntaxNode,
12}; 10};
13use ra_db::{SourceRootId, FileId, FilePosition, Cancelable}; 11use ra_db::{SourceRootId, FileId, Cancelable};
14use relative_path::RelativePathBuf; 12use relative_path::RelativePathBuf;
15 13
16use crate::{ 14use crate::{
@@ -30,68 +28,6 @@ pub struct Module {
30} 28}
31 29
32impl Module { 30impl Module {
33 /// Lookup `Module` by `FileId`. Note that this is inherently
34 /// lossy transformation: in general, a single source might correspond to
35 /// several modules.
36 pub fn guess_from_file_id(
37 db: &impl HirDatabase,
38 file_id: FileId,
39 ) -> Cancelable<Option<Module>> {
40 let module_source = ModuleSource::new_file(db, file_id);
41 Module::guess_from_source(db, module_source)
42 }
43
44 /// Lookup `Module` by position in the source code. Note that this
45 /// is inherently lossy transformation: in general, a single source might
46 /// correspond to several modules.
47 pub fn guess_from_position(
48 db: &impl HirDatabase,
49 position: FilePosition,
50 ) -> Cancelable<Option<Module>> {
51 let file = db.source_file(position.file_id);
52 let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset)
53 {
54 Some(m) if !m.has_semi() => ModuleSource::new_inline(db, position.file_id, m),
55 _ => ModuleSource::new_file(db, position.file_id),
56 };
57 Module::guess_from_source(db, module_source)
58 }
59
60 pub fn guess_from_child_node(
61 db: &impl HirDatabase,
62 file_id: FileId,
63 node: SyntaxNodeRef,
64 ) -> Cancelable<Option<Module>> {
65 let module_source = if let Some(m) = node
66 .ancestors()
67 .filter_map(ast::Module::cast)
68 .find(|it| !it.has_semi())
69 {
70 ModuleSource::new_inline(db, file_id, m)
71 } else {
72 ModuleSource::new_file(db, file_id)
73 };
74 Module::guess_from_source(db, module_source)
75 }
76
77 fn guess_from_source(
78 db: &impl HirDatabase,
79 module_source: ModuleSource,
80 ) -> Cancelable<Option<Module>> {
81 let source_root_id = db.file_source_root(module_source.file_id());
82 let module_tree = db.module_tree(source_root_id)?;
83
84 let res = match module_tree.any_module_for_source(module_source) {
85 None => None,
86 Some(module_id) => Some(Module {
87 tree: module_tree,
88 source_root_id,
89 module_id,
90 }),
91 };
92 Ok(res)
93 }
94
95 pub(super) fn new( 31 pub(super) fn new(
96 db: &impl HirDatabase, 32 db: &impl HirDatabase,
97 source_root_id: SourceRootId, 33 source_root_id: SourceRootId,
@@ -225,7 +161,8 @@ impl ModuleTree {
225 .collect() 161 .collect()
226 } 162 }
227 163
228 fn any_module_for_source(&self, source: ModuleSource) -> Option<ModuleId> { 164 //TODO: move to source binders?
165 pub(crate) fn any_module_for_source(&self, source: ModuleSource) -> Option<ModuleId> {
229 self.modules_for_source(source).pop() 166 self.modules_for_source(source).pop()
230 } 167 }
231} 168}
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 {
363 fn item_map(fixture: &str) -> (Arc<hir::ItemMap>, hir::ModuleId) { 363 fn item_map(fixture: &str) -> (Arc<hir::ItemMap>, hir::ModuleId) {
364 let (db, pos) = MockDatabase::with_position(fixture); 364 let (db, pos) = MockDatabase::with_position(fixture);
365 let source_root = db.file_source_root(pos.file_id); 365 let source_root = db.file_source_root(pos.file_id);
366 let module = hir::Module::guess_from_position(&db, pos).unwrap().unwrap(); 366 let module = hir::source_binder::module_from_position(&db, pos)
367 .unwrap()
368 .unwrap();
367 let module_id = module.module_id; 369 let module_id = module.module_id;
368 (db.item_map(source_root).unwrap(), module_id) 370 (db.item_map(source_root).unwrap(), module_id)
369 } 371 }
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 @@
1/// Lookup hir elements using position in the source code. This is a lossy
2/// transformation: in general, a single source might correspond to several
3/// modules, functions, etc, due to macros, cfgs and `#[path=]` attributes on
4/// modules.
5///
6/// So, this modules should not be used during hir construction, it exists
7/// purely for "IDE needs".
8use ra_db::{FileId, FilePosition, Cancelable};
9use ra_editor::find_node_at_offset;
10use ra_syntax::{
11 ast::{self, AstNode},
12 SyntaxNodeRef,
13};
14
15use crate::{
16 HirDatabase, Module, Function, SourceItemId,
17 module::ModuleSource,
18 DefKind, DefLoc
19};
20
21/// Locates the module by `FileId`. Picks topmost module in the file.
22pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Cancelable<Option<Module>> {
23 let module_source = ModuleSource::new_file(db, file_id);
24 module_from_source(db, module_source)
25}
26
27/// Locates the module by position in the source code.
28pub fn module_from_position(
29 db: &impl HirDatabase,
30 position: FilePosition,
31) -> Cancelable<Option<Module>> {
32 let file = db.source_file(position.file_id);
33 let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) {
34 Some(m) if !m.has_semi() => ModuleSource::new_inline(db, position.file_id, m),
35 _ => ModuleSource::new_file(db, position.file_id),
36 };
37 module_from_source(db, module_source)
38}
39
40/// Locates the module by child syntax element within the module
41pub fn module_from_child_node(
42 db: &impl HirDatabase,
43 file_id: FileId,
44 child: SyntaxNodeRef,
45) -> Cancelable<Option<Module>> {
46 let module_source = if let Some(m) = child
47 .ancestors()
48 .filter_map(ast::Module::cast)
49 .find(|it| !it.has_semi())
50 {
51 ModuleSource::new_inline(db, file_id, m)
52 } else {
53 ModuleSource::new_file(db, file_id)
54 };
55 module_from_source(db, module_source)
56}
57
58fn module_from_source(
59 db: &impl HirDatabase,
60 module_source: ModuleSource,
61) -> Cancelable<Option<Module>> {
62 let source_root_id = db.file_source_root(module_source.file_id());
63 let module_tree = db.module_tree(source_root_id)?;
64
65 let module_id = ctry!(module_tree.any_module_for_source(module_source));
66 Ok(Some(Module::new(db, source_root_id, module_id)?))
67}
68
69pub fn function_from_source(
70 db: &impl HirDatabase,
71 file_id: FileId,
72 fn_def: ast::FnDef,
73) -> Cancelable<Option<Function>> {
74 let module = ctry!(module_from_child_node(db, file_id, fn_def.syntax())?);
75 let file_items = db.file_items(file_id);
76 let item_id = file_items.id_of(fn_def.syntax());
77 let source_item_id = SourceItemId { file_id, item_id };
78 let def_loc = DefLoc {
79 kind: DefKind::Function,
80 source_root_id: module.source_root_id,
81 module_id: module.module_id,
82 source_item_id,
83 };
84 Ok(Some(Function::new(def_loc.id(db))))
85}
86
87pub fn function_from_child_node(
88 db: &impl HirDatabase,
89 file_id: FileId,
90 node: SyntaxNodeRef,
91) -> Cancelable<Option<Function>> {
92 let fn_def = ctry!(node.ancestors().find_map(ast::FnDef::cast));
93 function_from_source(db, file_id, fn_def)
94}