diff options
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 34 |
1 files changed, 21 insertions, 13 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index f08827ed3..f3bccd8ed 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -141,13 +141,16 @@ impl SourceAnalyzer { | |||
141 | node: &SyntaxNode, | 141 | node: &SyntaxNode, |
142 | offset: Option<TextUnit>, | 142 | offset: Option<TextUnit>, |
143 | ) -> SourceAnalyzer { | 143 | ) -> SourceAnalyzer { |
144 | let def_with_body = def_with_body_from_child_node(db, Source::new(file_id.into(), node)); | 144 | let node_source = Source::new(file_id.into(), node); |
145 | let def_with_body = def_with_body_from_child_node(db, node_source); | ||
145 | if let Some(def) = def_with_body { | 146 | if let Some(def) = def_with_body { |
146 | let source_map = def.body_source_map(db); | 147 | let source_map = def.body_source_map(db); |
147 | let scopes = def.expr_scopes(db); | 148 | let scopes = def.expr_scopes(db); |
148 | let scope = match offset { | 149 | let scope = match offset { |
149 | None => scope_for(&scopes, &source_map, file_id.into(), &node), | 150 | None => scope_for(&scopes, &source_map, node_source), |
150 | Some(offset) => scope_for_offset(&scopes, &source_map, file_id.into(), offset), | 151 | Some(offset) => { |
152 | scope_for_offset(&scopes, &source_map, Source::new(file_id.into(), offset)) | ||
153 | } | ||
151 | }; | 154 | }; |
152 | let resolver = expr::resolver_for_scope(db, def, scope); | 155 | let resolver = expr::resolver_for_scope(db, def, scope); |
153 | SourceAnalyzer { | 156 | SourceAnalyzer { |
@@ -287,7 +290,8 @@ impl SourceAnalyzer { | |||
287 | let name = name_ref.as_name(); | 290 | let name = name_ref.as_name(); |
288 | let source_map = self.body_source_map.as_ref()?; | 291 | let source_map = self.body_source_map.as_ref()?; |
289 | let scopes = self.scopes.as_ref()?; | 292 | let scopes = self.scopes.as_ref()?; |
290 | let scope = scope_for(scopes, source_map, self.file_id.into(), name_ref.syntax())?; | 293 | let scope = |
294 | scope_for(scopes, source_map, Source::new(self.file_id.into(), name_ref.syntax()))?; | ||
291 | let entry = scopes.resolve_name_in_scope(scope, &name)?; | 295 | let entry = scopes.resolve_name_in_scope(scope, &name)?; |
292 | Some(ScopeEntryWithSyntax { | 296 | Some(ScopeEntryWithSyntax { |
293 | name: entry.name().clone(), | 297 | name: entry.name().clone(), |
@@ -408,20 +412,19 @@ impl SourceAnalyzer { | |||
408 | fn scope_for( | 412 | fn scope_for( |
409 | scopes: &ExprScopes, | 413 | scopes: &ExprScopes, |
410 | source_map: &BodySourceMap, | 414 | source_map: &BodySourceMap, |
411 | file_id: HirFileId, | 415 | node: Source<&SyntaxNode>, |
412 | node: &SyntaxNode, | ||
413 | ) -> Option<ScopeId> { | 416 | ) -> Option<ScopeId> { |
414 | node.ancestors() | 417 | node.ast |
418 | .ancestors() | ||
415 | .filter_map(ast::Expr::cast) | 419 | .filter_map(ast::Expr::cast) |
416 | .filter_map(|it| source_map.node_expr(Source { file_id, ast: &it })) | 420 | .filter_map(|it| source_map.node_expr(Source::new(node.file_id, &it))) |
417 | .find_map(|it| scopes.scope_for(it)) | 421 | .find_map(|it| scopes.scope_for(it)) |
418 | } | 422 | } |
419 | 423 | ||
420 | fn scope_for_offset( | 424 | fn scope_for_offset( |
421 | scopes: &ExprScopes, | 425 | scopes: &ExprScopes, |
422 | source_map: &BodySourceMap, | 426 | source_map: &BodySourceMap, |
423 | file_id: HirFileId, | 427 | offset: Source<TextUnit>, |
424 | offset: TextUnit, | ||
425 | ) -> Option<ScopeId> { | 428 | ) -> Option<ScopeId> { |
426 | scopes | 429 | scopes |
427 | .scope_by_expr() | 430 | .scope_by_expr() |
@@ -429,7 +432,7 @@ fn scope_for_offset( | |||
429 | .filter_map(|(id, scope)| { | 432 | .filter_map(|(id, scope)| { |
430 | let source = source_map.expr_syntax(*id)?; | 433 | let source = source_map.expr_syntax(*id)?; |
431 | // FIXME: correctly handle macro expansion | 434 | // FIXME: correctly handle macro expansion |
432 | if source.file_id != file_id { | 435 | if source.file_id != offset.file_id { |
433 | return None; | 436 | return None; |
434 | } | 437 | } |
435 | let syntax_node_ptr = | 438 | let syntax_node_ptr = |
@@ -438,9 +441,14 @@ fn scope_for_offset( | |||
438 | }) | 441 | }) |
439 | // find containing scope | 442 | // find containing scope |
440 | .min_by_key(|(ptr, _scope)| { | 443 | .min_by_key(|(ptr, _scope)| { |
441 | (!(ptr.range().start() <= offset && offset <= ptr.range().end()), ptr.range().len()) | 444 | ( |
445 | !(ptr.range().start() <= offset.ast && offset.ast <= ptr.range().end()), | ||
446 | ptr.range().len(), | ||
447 | ) | ||
448 | }) | ||
449 | .map(|(ptr, scope)| { | ||
450 | adjust(scopes, source_map, ptr, offset.file_id, offset.ast).unwrap_or(*scope) | ||
442 | }) | 451 | }) |
443 | .map(|(ptr, scope)| adjust(scopes, source_map, ptr, file_id, offset).unwrap_or(*scope)) | ||
444 | } | 452 | } |
445 | 453 | ||
446 | // XXX: during completion, cursor might be outside of any particular | 454 | // XXX: during completion, cursor might be outside of any particular |