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.rs82
1 files changed, 80 insertions, 2 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index d1eaccf23..59f782277 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -9,13 +9,14 @@ use 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},
12 algo::find_node_at_offset, 12 algo::{find_node_at_offset, find_leaf_at_offset},
13}; 13};
14 14
15use crate::{ 15use crate::{
16 HirDatabase, Function, ModuleDef, Struct, Enum, 16 HirDatabase, Function, ModuleDef, Struct, Enum,
17 AsName, Module, HirFileId, Crate, 17 AsName, Module, HirFileId, Crate, Trait, Resolver,
18 ids::{LocationCtx, SourceFileItemId}, 18 ids::{LocationCtx, SourceFileItemId},
19 expr
19}; 20};
20 21
21/// Locates the module by `FileId`. Picks topmost module in the file. 22/// Locates the module by `FileId`. Picks topmost module in the file.
@@ -151,6 +152,19 @@ pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::E
151 } 152 }
152} 153}
153 154
155pub fn trait_from_module(
156 db: &impl HirDatabase,
157 module: Module,
158 trait_def: &ast::TraitDef,
159) -> Trait {
160 let (file_id, _) = module.definition_source(db);
161 let file_id = file_id.into();
162 let ctx = LocationCtx::new(db, module, file_id);
163 Trait {
164 id: ctx.to_def(trait_def),
165 }
166}
167
154pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, TextRange)> { 168pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, TextRange)> {
155 let module = match module_from_file_id(db, file_id) { 169 let module = match module_from_file_id(db, file_id) {
156 Some(it) => it, 170 Some(it) => it,
@@ -188,3 +202,67 @@ pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, Te
188 202
189 res 203 res
190} 204}
205
206pub fn resolver_for_position(db: &impl HirDatabase, position: FilePosition) -> Resolver {
207 let file_id = position.file_id;
208 let file = db.parse(file_id);
209 find_leaf_at_offset(file.syntax(), position.offset)
210 .find_map(|node| {
211 node.ancestors().find_map(|node| {
212 if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() {
213 if let Some(func) = function_from_child_node(db, file_id, node) {
214 let scopes = func.scopes(db);
215 let scope = scopes.scope_for_offset(position.offset);
216 Some(expr::resolver_for_scope(func.body(db), db, scope))
217 } else {
218 // TODO const/static/array length
219 None
220 }
221 } else if let Some(module) = ast::Module::cast(node) {
222 Some(module_from_declaration(db, file_id, module)?.resolver(db))
223 } else if let Some(_) = ast::SourceFile::cast(node) {
224 Some(module_from_source(db, file_id.into(), None)?.resolver(db))
225 } else if let Some(s) = ast::StructDef::cast(node) {
226 let module = module_from_child_node(db, file_id, s.syntax())?;
227 Some(struct_from_module(db, module, s).resolver(db))
228 } else if let Some(e) = ast::EnumDef::cast(node) {
229 let module = module_from_child_node(db, file_id, e.syntax())?;
230 Some(enum_from_module(db, module, e).resolver(db))
231 } else {
232 // TODO add missing cases
233 None
234 }
235 })
236 })
237 .unwrap_or_default()
238}
239
240pub fn resolver_for_node(db: &impl HirDatabase, file_id: FileId, node: &SyntaxNode) -> Resolver {
241 node.ancestors()
242 .find_map(|node| {
243 if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() {
244 if let Some(func) = function_from_child_node(db, file_id, node) {
245 let scopes = func.scopes(db);
246 let scope = scopes.scope_for(&node);
247 Some(expr::resolver_for_scope(func.body(db), db, scope))
248 } else {
249 // TODO const/static/array length
250 None
251 }
252 } else if let Some(module) = ast::Module::cast(node) {
253 Some(module_from_declaration(db, file_id, module)?.resolver(db))
254 } else if let Some(_) = ast::SourceFile::cast(node) {
255 Some(module_from_source(db, file_id.into(), None)?.resolver(db))
256 } else if let Some(s) = ast::StructDef::cast(node) {
257 let module = module_from_child_node(db, file_id, s.syntax())?;
258 Some(struct_from_module(db, module, s).resolver(db))
259 } else if let Some(e) = ast::EnumDef::cast(node) {
260 let module = module_from_child_node(db, file_id, e.syntax())?;
261 Some(enum_from_module(db, module, e).resolver(db))
262 } else {
263 // TODO add missing cases
264 None
265 }
266 })
267 .unwrap_or_default()
268}