aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/source_binder.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/source_binder.rs')
-rw-r--r--crates/ra_hir/src/source_binder.rs62
1 files changed, 25 insertions, 37 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 70dd850d7..7ab8eeae2 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -5,7 +5,7 @@
5/// 5///
6/// So, this modules should not be used during hir construction, it exists 6/// So, this modules should not be used during hir construction, it exists
7/// purely for "IDE needs". 7/// purely for "IDE needs".
8use ra_db::{FileId, FilePosition, Cancelable}; 8use ra_db::{FileId, FilePosition};
9use ra_syntax::{ 9use ra_syntax::{
10 SmolStr, TextRange, SyntaxNode, 10 SmolStr, TextRange, SyntaxNode,
11 ast::{self, AstNode, NameOwner}, 11 ast::{self, AstNode, NameOwner},
@@ -18,7 +18,7 @@ use crate::{
18}; 18};
19 19
20/// Locates the module by `FileId`. Picks topmost module in the file. 20/// Locates the module by `FileId`. Picks topmost module in the file.
21pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Cancelable<Option<Module>> { 21pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Option<Module> {
22 let module_source = SourceItemId { 22 let module_source = SourceItemId {
23 file_id: file_id.into(), 23 file_id: file_id.into(),
24 item_id: None, 24 item_id: None,
@@ -31,25 +31,22 @@ pub fn module_from_declaration(
31 db: &impl HirDatabase, 31 db: &impl HirDatabase,
32 file_id: FileId, 32 file_id: FileId,
33 decl: &ast::Module, 33 decl: &ast::Module,
34) -> Cancelable<Option<Module>> { 34) -> Option<Module> {
35 let parent_module = module_from_file_id(db, file_id)?; 35 let parent_module = module_from_file_id(db, file_id);
36 let child_name = decl.name(); 36 let child_name = decl.name();
37 match (parent_module, child_name) { 37 match (parent_module, child_name) {
38 (Some(parent_module), Some(child_name)) => { 38 (Some(parent_module), Some(child_name)) => {
39 if let Some(child) = parent_module.child(db, &child_name.as_name())? { 39 if let Some(child) = parent_module.child(db, &child_name.as_name()) {
40 return Ok(Some(child)); 40 return Some(child);
41 } 41 }
42 } 42 }
43 _ => (), 43 _ => (),
44 } 44 }
45 Ok(None) 45 None
46} 46}
47 47
48/// Locates the module by position in the source code. 48/// Locates the module by position in the source code.
49pub fn module_from_position( 49pub fn module_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Module> {
50 db: &impl HirDatabase,
51 position: FilePosition,
52) -> Cancelable<Option<Module>> {
53 let file = db.source_file(position.file_id); 50 let file = db.source_file(position.file_id);
54 match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) { 51 match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) {
55 Some(m) if !m.has_semi() => module_from_inline(db, position.file_id.into(), m), 52 Some(m) if !m.has_semi() => module_from_inline(db, position.file_id.into(), m),
@@ -61,7 +58,7 @@ fn module_from_inline(
61 db: &impl HirDatabase, 58 db: &impl HirDatabase,
62 file_id: FileId, 59 file_id: FileId,
63 module: &ast::Module, 60 module: &ast::Module,
64) -> Cancelable<Option<Module>> { 61) -> Option<Module> {
65 assert!(!module.has_semi()); 62 assert!(!module.has_semi());
66 let file_id = file_id.into(); 63 let file_id = file_id.into();
67 let file_items = db.file_items(file_id); 64 let file_items = db.file_items(file_id);
@@ -78,7 +75,7 @@ pub fn module_from_child_node(
78 db: &impl HirDatabase, 75 db: &impl HirDatabase,
79 file_id: FileId, 76 file_id: FileId,
80 child: &SyntaxNode, 77 child: &SyntaxNode,
81) -> Cancelable<Option<Module>> { 78) -> Option<Module> {
82 if let Some(m) = child 79 if let Some(m) = child
83 .ancestors() 80 .ancestors()
84 .filter_map(ast::Module::cast) 81 .filter_map(ast::Module::cast)
@@ -90,22 +87,16 @@ pub fn module_from_child_node(
90 } 87 }
91} 88}
92 89
93fn module_from_source(db: &impl HirDatabase, source: SourceItemId) -> Cancelable<Option<Module>> { 90fn module_from_source(db: &impl HirDatabase, source: SourceItemId) -> Option<Module> {
94 let source_root_id = db.file_source_root(source.file_id.as_original_file()); 91 let source_root_id = db.file_source_root(source.file_id.as_original_file());
95 let module_tree = db.module_tree(source_root_id); 92 let module_tree = db.module_tree(source_root_id);
96 let module_id = ctry!(module_tree.find_module_by_source(source)); 93 let module_id = module_tree.find_module_by_source(source)?;
97 Ok(Some(Module::from_module_id(db, source_root_id, module_id)?)) 94 Some(Module::from_module_id(db, source_root_id, module_id))
98} 95}
99 96
100pub fn function_from_position( 97pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Function> {
101 db: &impl HirDatabase,
102 position: FilePosition,
103) -> Cancelable<Option<Function>> {
104 let file = db.source_file(position.file_id); 98 let file = db.source_file(position.file_id);
105 let fn_def = ctry!(find_node_at_offset::<ast::FnDef>( 99 let fn_def = find_node_at_offset::<ast::FnDef>(file.syntax(), position.offset)?;
106 file.syntax(),
107 position.offset
108 ));
109 function_from_source(db, position.file_id, fn_def) 100 function_from_source(db, position.file_id, fn_def)
110} 101}
111 102
@@ -113,10 +104,10 @@ pub fn function_from_source(
113 db: &impl HirDatabase, 104 db: &impl HirDatabase,
114 file_id: FileId, 105 file_id: FileId,
115 fn_def: &ast::FnDef, 106 fn_def: &ast::FnDef,
116) -> Cancelable<Option<Function>> { 107) -> Option<Function> {
117 let module = ctry!(module_from_child_node(db, file_id, fn_def.syntax())?); 108 let module = module_from_child_node(db, file_id, fn_def.syntax())?;
118 let res = function_from_module(db, &module, fn_def); 109 let res = function_from_module(db, &module, fn_def);
119 Ok(Some(res)) 110 Some(res)
120} 111}
121 112
122pub fn function_from_module( 113pub fn function_from_module(
@@ -145,21 +136,18 @@ pub fn function_from_child_node(
145 db: &impl HirDatabase, 136 db: &impl HirDatabase,
146 file_id: FileId, 137 file_id: FileId,
147 node: &SyntaxNode, 138 node: &SyntaxNode,
148) -> Cancelable<Option<Function>> { 139) -> Option<Function> {
149 let fn_def = ctry!(node.ancestors().find_map(ast::FnDef::cast)); 140 let fn_def = node.ancestors().find_map(ast::FnDef::cast)?;
150 function_from_source(db, file_id, fn_def) 141 function_from_source(db, file_id, fn_def)
151} 142}
152 143
153pub fn macro_symbols( 144pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, TextRange)> {
154 db: &impl HirDatabase, 145 let module = match module_from_file_id(db, file_id) {
155 file_id: FileId,
156) -> Cancelable<Vec<(SmolStr, TextRange)>> {
157 let module = match module_from_file_id(db, file_id)? {
158 Some(it) => it, 146 Some(it) => it,
159 None => return Ok(Vec::new()), 147 None => return Vec::new(),
160 }; 148 };
161 let loc = module.def_id.loc(db); 149 let loc = module.def_id.loc(db);
162 let items = db.input_module_items(loc.source_root_id, loc.module_id)?; 150 let items = db.input_module_items(loc.source_root_id, loc.module_id);
163 let mut res = Vec::new(); 151 let mut res = Vec::new();
164 152
165 for macro_call_id in items 153 for macro_call_id in items
@@ -184,5 +172,5 @@ pub fn macro_symbols(
184 } 172 }
185 } 173 }
186 174
187 Ok(res) 175 res
188} 176}