diff options
Diffstat (limited to 'crates/ra_hir/src/expr')
-rw-r--r-- | crates/ra_hir/src/expr/scope.rs | 55 |
1 files changed, 24 insertions, 31 deletions
diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index b7971088d..9202e3671 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs | |||
@@ -58,28 +58,19 @@ impl ExprScopes { | |||
58 | scopes | 58 | scopes |
59 | } | 59 | } |
60 | 60 | ||
61 | pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] { | 61 | pub fn body(&self) -> Arc<Body> { |
62 | &self.scopes[scope].entries | 62 | self.body.clone() |
63 | } | 63 | } |
64 | 64 | ||
65 | pub fn scope_chain_for<'a>(&'a self, expr: ExprId) -> impl Iterator<Item = ScopeId> + 'a { | 65 | pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] { |
66 | generate(self.scope_for(expr), move |&scope| { | 66 | &self.scopes[scope].entries |
67 | self.scopes[scope].parent | ||
68 | }) | ||
69 | } | 67 | } |
70 | 68 | ||
71 | pub fn resolve_local_name<'a>( | 69 | pub fn scope_chain_for<'a>( |
72 | &'a self, | 70 | &'a self, |
73 | context_expr: ExprId, | 71 | scope: Option<ScopeId>, |
74 | name: Name, | 72 | ) -> impl Iterator<Item = ScopeId> + 'a { |
75 | ) -> Option<&'a ScopeEntry> { | 73 | generate(scope, move |&scope| self.scopes[scope].parent) |
76 | let mut shadowed = FxHashSet::default(); | ||
77 | let ret = self | ||
78 | .scope_chain_for(context_expr) | ||
79 | .flat_map(|scope| self.entries(scope).iter()) | ||
80 | .filter(|entry| shadowed.insert(entry.name())) | ||
81 | .find(|entry| entry.name() == &name); | ||
82 | ret | ||
83 | } | 74 | } |
84 | 75 | ||
85 | fn root_scope(&mut self) -> ScopeId { | 76 | fn root_scope(&mut self) -> ScopeId { |
@@ -122,7 +113,7 @@ impl ExprScopes { | |||
122 | self.scope_for.insert(node, scope); | 113 | self.scope_for.insert(node, scope); |
123 | } | 114 | } |
124 | 115 | ||
125 | fn scope_for(&self, expr: ExprId) -> Option<ScopeId> { | 116 | pub fn scope_for(&self, expr: ExprId) -> Option<ScopeId> { |
126 | self.scope_for.get(&expr).map(|&scope| scope) | 117 | self.scope_for.get(&expr).map(|&scope| scope) |
127 | } | 118 | } |
128 | } | 119 | } |
@@ -150,18 +141,14 @@ impl ScopeEntryWithSyntax { | |||
150 | } | 141 | } |
151 | 142 | ||
152 | impl ScopesWithSyntaxMapping { | 143 | impl ScopesWithSyntaxMapping { |
153 | pub fn scope_chain<'a>(&'a self, node: &SyntaxNode) -> impl Iterator<Item = ScopeId> + 'a { | 144 | fn scope_chain<'a>(&'a self, node: &SyntaxNode) -> impl Iterator<Item = ScopeId> + 'a { |
154 | generate(self.scope_for(node), move |&scope| { | 145 | generate(self.scope_for(node), move |&scope| { |
155 | self.scopes.scopes[scope].parent | 146 | self.scopes.scopes[scope].parent |
156 | }) | 147 | }) |
157 | } | 148 | } |
158 | 149 | ||
159 | pub fn scope_chain_for_offset<'a>( | 150 | pub fn scope_for_offset<'a>(&'a self, offset: TextUnit) -> Option<ScopeId> { |
160 | &'a self, | 151 | self.scopes |
161 | offset: TextUnit, | ||
162 | ) -> impl Iterator<Item = ScopeId> + 'a { | ||
163 | let scope = self | ||
164 | .scopes | ||
165 | .scope_for | 152 | .scope_for |
166 | .iter() | 153 | .iter() |
167 | .filter_map(|(id, scope)| Some((self.syntax_mapping.expr_syntax(*id)?, scope))) | 154 | .filter_map(|(id, scope)| Some((self.syntax_mapping.expr_syntax(*id)?, scope))) |
@@ -172,13 +159,12 @@ impl ScopesWithSyntaxMapping { | |||
172 | ptr.range().len(), | 159 | ptr.range().len(), |
173 | ) | 160 | ) |
174 | }) | 161 | }) |
175 | .map(|(ptr, scope)| self.adjust(ptr, *scope, offset)); | 162 | .map(|(ptr, scope)| self.adjust(ptr, *scope, offset)) |
176 | |||
177 | generate(scope, move |&scope| self.scopes.scopes[scope].parent) | ||
178 | } | 163 | } |
179 | 164 | ||
180 | // XXX: during completion, cursor might be outside of any particular | 165 | // XXX: during completion, cursor might be outside of any particular |
181 | // expression. Try to figure out the correct scope... | 166 | // expression. Try to figure out the correct scope... |
167 | // TODO: move this to source binder? | ||
182 | fn adjust(&self, ptr: SyntaxNodePtr, original_scope: ScopeId, offset: TextUnit) -> ScopeId { | 168 | fn adjust(&self, ptr: SyntaxNodePtr, original_scope: ScopeId, offset: TextUnit) -> ScopeId { |
183 | let r = ptr.range(); | 169 | let r = ptr.range(); |
184 | let child_scopes = self | 170 | let child_scopes = self |
@@ -238,7 +224,7 @@ impl ScopesWithSyntaxMapping { | |||
238 | .collect() | 224 | .collect() |
239 | } | 225 | } |
240 | 226 | ||
241 | fn scope_for(&self, node: &SyntaxNode) -> Option<ScopeId> { | 227 | pub fn scope_for(&self, node: &SyntaxNode) -> Option<ScopeId> { |
242 | node.ancestors() | 228 | node.ancestors() |
243 | .map(SyntaxNodePtr::new) | 229 | .map(SyntaxNodePtr::new) |
244 | .filter_map(|ptr| self.syntax_mapping.syntax_expr(ptr)) | 230 | .filter_map(|ptr| self.syntax_mapping.syntax_expr(ptr)) |
@@ -336,6 +322,7 @@ pub struct ReferenceDescriptor { | |||
336 | mod tests { | 322 | mod tests { |
337 | use ra_syntax::{SourceFile, algo::find_node_at_offset}; | 323 | use ra_syntax::{SourceFile, algo::find_node_at_offset}; |
338 | use test_utils::{extract_offset, assert_eq_text}; | 324 | use test_utils::{extract_offset, assert_eq_text}; |
325 | use ra_arena::ArenaId; | ||
339 | 326 | ||
340 | use crate::expr; | 327 | use crate::expr; |
341 | 328 | ||
@@ -354,7 +341,10 @@ mod tests { | |||
354 | let file = SourceFile::parse(&code); | 341 | let file = SourceFile::parse(&code); |
355 | let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); | 342 | let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); |
356 | let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); | 343 | let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); |
357 | let body_hir = expr::collect_fn_body_syntax(fn_def); | 344 | let irrelevant_function = Function { |
345 | id: crate::ids::FunctionId::from_raw(0.into()), | ||
346 | }; | ||
347 | let body_hir = expr::collect_fn_body_syntax(irrelevant_function, fn_def); | ||
358 | let scopes = ExprScopes::new(Arc::clone(body_hir.body())); | 348 | let scopes = ExprScopes::new(Arc::clone(body_hir.body())); |
359 | let scopes = ScopesWithSyntaxMapping { | 349 | let scopes = ScopesWithSyntaxMapping { |
360 | scopes: Arc::new(scopes), | 350 | scopes: Arc::new(scopes), |
@@ -454,7 +444,10 @@ mod tests { | |||
454 | let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); | 444 | let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); |
455 | let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); | 445 | let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); |
456 | 446 | ||
457 | let body_hir = expr::collect_fn_body_syntax(fn_def); | 447 | let irrelevant_function = Function { |
448 | id: crate::ids::FunctionId::from_raw(0.into()), | ||
449 | }; | ||
450 | let body_hir = expr::collect_fn_body_syntax(irrelevant_function, fn_def); | ||
458 | let scopes = ExprScopes::new(Arc::clone(body_hir.body())); | 451 | let scopes = ExprScopes::new(Arc::clone(body_hir.body())); |
459 | let scopes = ScopesWithSyntaxMapping { | 452 | let scopes = ScopesWithSyntaxMapping { |
460 | scopes: Arc::new(scopes), | 453 | scopes: Arc::new(scopes), |