aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/source_binder.rs
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-02-01 22:37:59 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-02-01 22:37:59 +0000
commit4447019f4b5f24728bb7b91b161755ddb373c74c (patch)
treec53ff3531cbbad182e821eb92fa9ad201d2bff0c /crates/ra_hir/src/source_binder.rs
parent2b5c226e86892113bcab478cdf4c9adaf1e7b2f6 (diff)
parentc5852f422ff45adaa21815c1a15e03b067a56a82 (diff)
Merge #693
693: Name resolution refactoring r=matklad a=flodiebold This is still very WIP, but it's becoming quite big and I want to make sure this isn't going in a completely bad direction :sweat_smile:. I'm not really happy with how the path resolution looks, and I'm not sure `PerNs<Resolution>` is the best return type -- there are 'this cannot happen in the (types/values) namespace' cases everywhere. I also want to unify the `resolver` and `nameres` namespaces once I'm done switching everything to `Resolver`. Also, `Resolver` only has a lifetime because it needs to have a reference to the `ItemMap` during import resolution :confused: The differences in the completion snapshots are almost completely just ordering (except it completes `Self` as well now), so I changed it to sort the completions before snapshotting. Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/source_binder.rs')
-rw-r--r--crates/ra_hir/src/source_binder.rs69
1 files changed, 67 insertions, 2 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index a1b94ed9c..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, Trait, 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.
@@ -201,3 +202,67 @@ pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, Te
201 202
202 res 203 res
203} 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}