aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/expr
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/expr')
-rw-r--r--crates/ra_hir/src/expr/scope.rs55
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
152impl ScopesWithSyntaxMapping { 143impl 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 {
336mod tests { 322mod 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),