aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-01-27 19:50:57 +0000
committerFlorian Diebold <[email protected]>2019-02-01 21:45:25 +0000
commit33ff7b56ff353410e7bcb7aed27004d4f0a57d8e (patch)
tree88dba144f41cdbd20584306a296031cb8f0ced3a /crates/ra_hir
parent6b076f1931d7dc324d7bbbc4c1df9f7c1c1db8b7 (diff)
Use the new Resolver API in completion
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/expr.rs18
-rw-r--r--crates/ra_hir/src/expr/scope.rs38
-rw-r--r--crates/ra_hir/src/nameres.rs9
-rw-r--r--crates/ra_hir/src/resolve.rs57
-rw-r--r--crates/ra_hir/src/source_binder.rs31
5 files changed, 115 insertions, 38 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 503a09f25..6c294bf10 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -72,11 +72,23 @@ impl Body {
72} 72}
73 73
74// needs arbitrary_self_types to be a method... or maybe move to the def? 74// needs arbitrary_self_types to be a method... or maybe move to the def?
75#[allow(dead_code)] 75pub fn resolver_for_expr(
76pub fn resolver_for_expr(body: Arc<Body>, db: &impl HirDatabase, expr_id: ExprId) -> Resolver { 76 body: Arc<Body>,
77 db: &impl HirDatabase,
78 expr_id: ExprId,
79) -> Resolver<'static> {
80 let scopes = db.expr_scopes(body.owner);
81 resolver_for_scope(body, db, scopes.scope_for(expr_id))
82}
83
84pub fn resolver_for_scope(
85 body: Arc<Body>,
86 db: &impl HirDatabase,
87 scope_id: Option<scope::ScopeId>,
88) -> Resolver<'static> {
77 let mut r = body.owner.resolver(db); 89 let mut r = body.owner.resolver(db);
78 let scopes = db.expr_scopes(body.owner); 90 let scopes = db.expr_scopes(body.owner);
79 let scope_chain = scopes.scope_chain_for(expr_id).collect::<Vec<_>>(); 91 let scope_chain = scopes.scope_chain_for(scope_id).collect::<Vec<_>>();
80 for scope in scope_chain.into_iter().rev() { 92 for scope in scope_chain.into_iter().rev() {
81 r = r.push_expr_scope(Arc::clone(&scopes), scope); 93 r = r.push_expr_scope(Arc::clone(&scopes), scope);
82 } 94 }
diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs
index 887ad8dd8..23f1c5e7f 100644
--- a/crates/ra_hir/src/expr/scope.rs
+++ b/crates/ra_hir/src/expr/scope.rs
@@ -62,25 +62,11 @@ impl ExprScopes {
62 &self.scopes[scope].entries 62 &self.scopes[scope].entries
63 } 63 }
64 64
65 pub fn scope_chain_for<'a>(&'a self, expr: ExprId) -> impl Iterator<Item = ScopeId> + 'a { 65 pub fn scope_chain_for<'a>(
66 generate(self.scope_for(expr), move |&scope| {
67 self.scopes[scope].parent
68 })
69 }
70
71 pub fn resolve_local_name<'a>(
72 &'a self, 66 &'a self,
73 context_expr: ExprId, 67 scope: Option<ScopeId>,
74 name: Name, 68 ) -> impl Iterator<Item = ScopeId> + 'a {
75 ) -> Option<&'a ScopeEntry> { 69 generate(scope, move |&scope| self.scopes[scope].parent)
76 // TODO replace by Resolver::resolve_name
77 let mut shadowed = FxHashSet::default();
78 let ret = self
79 .scope_chain_for(context_expr)
80 .flat_map(|scope| self.entries(scope).iter())
81 .filter(|entry| shadowed.insert(entry.name()))
82 .find(|entry| entry.name() == &name);
83 ret
84 } 70 }
85 71
86 fn root_scope(&mut self) -> ScopeId { 72 fn root_scope(&mut self) -> ScopeId {
@@ -123,7 +109,7 @@ impl ExprScopes {
123 self.scope_for.insert(node, scope); 109 self.scope_for.insert(node, scope);
124 } 110 }
125 111
126 fn scope_for(&self, expr: ExprId) -> Option<ScopeId> { 112 pub fn scope_for(&self, expr: ExprId) -> Option<ScopeId> {
127 self.scope_for.get(&expr).map(|&scope| scope) 113 self.scope_for.get(&expr).map(|&scope| scope)
128 } 114 }
129} 115}
@@ -151,18 +137,14 @@ impl ScopeEntryWithSyntax {
151} 137}
152 138
153impl ScopesWithSyntaxMapping { 139impl ScopesWithSyntaxMapping {
154 pub fn scope_chain<'a>(&'a self, node: &SyntaxNode) -> impl Iterator<Item = ScopeId> + 'a { 140 fn scope_chain<'a>(&'a self, node: &SyntaxNode) -> impl Iterator<Item = ScopeId> + 'a {
155 generate(self.scope_for(node), move |&scope| { 141 generate(self.scope_for(node), move |&scope| {
156 self.scopes.scopes[scope].parent 142 self.scopes.scopes[scope].parent
157 }) 143 })
158 } 144 }
159 145
160 pub fn scope_chain_for_offset<'a>( 146 pub fn scope_for_offset<'a>(&'a self, offset: TextUnit) -> Option<ScopeId> {
161 &'a self, 147 self.scopes
162 offset: TextUnit,
163 ) -> impl Iterator<Item = ScopeId> + 'a {
164 let scope = self
165 .scopes
166 .scope_for 148 .scope_for
167 .iter() 149 .iter()
168 .filter_map(|(id, scope)| Some((self.syntax_mapping.expr_syntax(*id)?, scope))) 150 .filter_map(|(id, scope)| Some((self.syntax_mapping.expr_syntax(*id)?, scope)))
@@ -173,9 +155,7 @@ impl ScopesWithSyntaxMapping {
173 ptr.range().len(), 155 ptr.range().len(),
174 ) 156 )
175 }) 157 })
176 .map(|(ptr, scope)| self.adjust(ptr, *scope, offset)); 158 .map(|(ptr, scope)| self.adjust(ptr, *scope, offset))
177
178 generate(scope, move |&scope| self.scopes.scopes[scope].parent)
179 } 159 }
180 160
181 // XXX: during completion, cursor might be outside of any particular 161 // XXX: during completion, cursor might be outside of any particular
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 193c6a977..9b020db81 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -81,6 +81,15 @@ pub struct PerNs<T> {
81 pub values: Option<T>, 81 pub values: Option<T>,
82} 82}
83 83
84impl<T> Default for PerNs<T> {
85 fn default() -> Self {
86 PerNs {
87 types: None,
88 values: None,
89 }
90 }
91}
92
84impl<T> PerNs<T> { 93impl<T> PerNs<T> {
85 pub fn none() -> PerNs<T> { 94 pub fn none() -> PerNs<T> {
86 PerNs { 95 PerNs {
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index 36daed65b..30cf9c69e 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -89,8 +89,20 @@ impl Resolver {
89 } 89 }
90 } 90 }
91 91
92 pub fn all_names(&self) -> FxHashMap<Name, Resolution> { 92 pub fn all_names(&self) -> FxHashMap<Name, PerNs<Resolution>> {
93 unimplemented!() 93 let mut names = FxHashMap::default();
94 for scope in &self.scopes {
95 scope.collect_names(&mut |name, res| {
96 let current: &mut PerNs<Resolution> = names.entry(name).or_default();
97 if current.types.is_none() {
98 current.types = res.types;
99 }
100 if current.values.is_none() {
101 current.values = res.values;
102 }
103 });
104 }
105 names
94 } 106 }
95 107
96 fn module(&self) -> Option<(&ItemMap, Module)> { 108 fn module(&self) -> Option<(&ItemMap, Module)> {
@@ -175,4 +187,45 @@ impl Scope {
175 } 187 }
176 } 188 }
177 } 189 }
190
191 fn collect_names(&self, f: &mut FnMut(Name, PerNs<Resolution>)) {
192 match self {
193 Scope::ModuleScope(m) => {
194 m.item_map[m.module.module_id]
195 .entries()
196 .for_each(|(name, res)| {
197 f(name.clone(), res.def.map(|def| Resolution::Def { def }));
198 })
199 }
200 Scope::ModuleScopeRef(m) => {
201 m.item_map[m.module.module_id]
202 .entries()
203 .for_each(|(name, res)| {
204 f(name.clone(), res.def.map(|def| Resolution::Def { def }));
205 })
206 }
207 Scope::GenericParams(gp) => {
208 for param in &gp.params {
209 f(
210 param.name.clone(),
211 PerNs::types(Resolution::GenericParam { idx: param.idx }),
212 )
213 }
214 }
215 Scope::ImplBlockScope(i) => {
216 f(
217 Name::self_type(),
218 PerNs::types(Resolution::SelfType(i.clone())),
219 );
220 }
221 Scope::ExprScope(e) => {
222 e.expr_scopes.entries(e.scope_id).iter().for_each(|e| {
223 f(
224 e.name().clone(),
225 PerNs::values(Resolution::LocalBinding { pat: e.pat() }),
226 );
227 });
228 }
229 }
230 }
178} 231}
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 1fdd7d087..998158b3e 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, Resolver, 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.
@@ -202,7 +203,29 @@ pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, Te
202 res 203 res
203} 204}
204 205
205#[allow(unused_variables)] 206pub fn resolver_for_position(db: &impl HirDatabase, position: FilePosition) -> Resolver<'static> {
206pub fn resolver_for_position(db: &impl HirDatabase, position: FilePosition) -> Resolver { 207 let file = db.parse(position.file_id);
207 unimplemented!() 208 find_leaf_at_offset(file.syntax(), position.offset)
209 .find_map(|node| {
210 node.ancestors().find_map(|node| {
211 if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() {
212 if let Some(func) = function_from_child_node(db, position.file_id, node) {
213 let scopes = func.scopes(db);
214 let scope = scopes.scope_for_offset(position.offset);
215 Some(expr::resolver_for_scope(func.body(db), db, scope))
216 } else {
217 // TODO const/static/array length
218 None
219 }
220 } else if let Some(module) = ast::Module::cast(node) {
221 Some(module_from_declaration(db, position.file_id, module)?.resolver(db))
222 } else if let Some(_) = ast::SourceFile::cast(node) {
223 Some(module_from_source(db, position.file_id.into(), None)?.resolver(db))
224 } else {
225 // TODO add missing cases
226 None
227 }
228 })
229 })
230 .unwrap_or_default()
208} 231}