diff options
Diffstat (limited to 'crates/ra_hir/src/source_binder.rs')
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 82 |
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}; | |||
9 | use ra_syntax::{ | 9 | use 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 | ||
15 | use crate::{ | 15 | use 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 | ||
155 | pub 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 | |||
154 | pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, TextRange)> { | 168 | pub 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 | |||
206 | pub 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 | |||
240 | pub 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 | } | ||