diff options
Diffstat (limited to 'crates/ra_hir/src/source_binder.rs')
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 41 |
1 files changed, 31 insertions, 10 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 56ff7da3a..fdbe5e8b0 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -27,9 +27,9 @@ use crate::{ | |||
27 | name, | 27 | name, |
28 | path::{PathKind, PathSegment}, | 28 | path::{PathKind, PathSegment}, |
29 | ty::method_resolution::implements_trait, | 29 | ty::method_resolution::implements_trait, |
30 | AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HirDatabase, HirFileId, | 30 | AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HasBody, HirDatabase, |
31 | MacroDef, Module, ModuleDef, Name, Path, PerNs, Resolution, Resolver, Static, Struct, Trait, | 31 | HirFileId, MacroDef, Module, ModuleDef, Name, Path, PerNs, Resolution, Resolver, Static, |
32 | Ty, | 32 | Struct, Trait, Ty, |
33 | }; | 33 | }; |
34 | 34 | ||
35 | /// Locates the module by `FileId`. Picks topmost module in the file. | 35 | /// Locates the module by `FileId`. Picks topmost module in the file. |
@@ -228,7 +228,7 @@ impl SourceAnalyzer { | |||
228 | let scopes = db.expr_scopes(def); | 228 | let scopes = db.expr_scopes(def); |
229 | let scope = match offset { | 229 | let scope = match offset { |
230 | None => scope_for(&scopes, &source_map, &node), | 230 | None => scope_for(&scopes, &source_map, &node), |
231 | Some(offset) => scope_for_offset(&scopes, &source_map, offset), | 231 | Some(offset) => scope_for_offset(&scopes, &source_map, file_id.into(), offset), |
232 | }; | 232 | }; |
233 | let resolver = expr::resolver_for_scope(def.body(db), db, scope); | 233 | let resolver = expr::resolver_for_scope(def.body(db), db, scope); |
234 | SourceAnalyzer { | 234 | SourceAnalyzer { |
@@ -330,6 +330,7 @@ impl SourceAnalyzer { | |||
330 | .body_source_map | 330 | .body_source_map |
331 | .as_ref()? | 331 | .as_ref()? |
332 | .pat_syntax(it)? | 332 | .pat_syntax(it)? |
333 | .ast // FIXME: ignoring file_id here is definitelly wrong | ||
333 | .map_a(|ptr| ptr.cast::<ast::BindPat>().unwrap()); | 334 | .map_a(|ptr| ptr.cast::<ast::BindPat>().unwrap()); |
334 | PathResolution::LocalBinding(pat_ptr) | 335 | PathResolution::LocalBinding(pat_ptr) |
335 | } | 336 | } |
@@ -354,7 +355,7 @@ impl SourceAnalyzer { | |||
354 | ret.and_then(|entry| { | 355 | ret.and_then(|entry| { |
355 | Some(ScopeEntryWithSyntax { | 356 | Some(ScopeEntryWithSyntax { |
356 | name: entry.name().clone(), | 357 | name: entry.name().clone(), |
357 | ptr: source_map.pat_syntax(entry.pat())?, | 358 | ptr: source_map.pat_syntax(entry.pat())?.ast, |
358 | }) | 359 | }) |
359 | }) | 360 | }) |
360 | } | 361 | } |
@@ -462,25 +463,35 @@ fn scope_for( | |||
462 | node: &SyntaxNode, | 463 | node: &SyntaxNode, |
463 | ) -> Option<ScopeId> { | 464 | ) -> Option<ScopeId> { |
464 | node.ancestors() | 465 | node.ancestors() |
465 | .map(|it| SyntaxNodePtr::new(&it)) | 466 | .filter_map(ast::Expr::cast) |
466 | .filter_map(|ptr| source_map.syntax_expr(ptr)) | 467 | .filter_map(|it| source_map.node_expr(&it)) |
467 | .find_map(|it| scopes.scope_for(it)) | 468 | .find_map(|it| scopes.scope_for(it)) |
468 | } | 469 | } |
469 | 470 | ||
470 | fn scope_for_offset( | 471 | fn scope_for_offset( |
471 | scopes: &ExprScopes, | 472 | scopes: &ExprScopes, |
472 | source_map: &BodySourceMap, | 473 | source_map: &BodySourceMap, |
474 | file_id: HirFileId, | ||
473 | offset: TextUnit, | 475 | offset: TextUnit, |
474 | ) -> Option<ScopeId> { | 476 | ) -> Option<ScopeId> { |
475 | scopes | 477 | scopes |
476 | .scope_by_expr() | 478 | .scope_by_expr() |
477 | .iter() | 479 | .iter() |
478 | .filter_map(|(id, scope)| Some((source_map.expr_syntax(*id)?, scope))) | 480 | .filter_map(|(id, scope)| { |
481 | let source = source_map.expr_syntax(*id)?; | ||
482 | // FIXME: correctly handle macro expansion | ||
483 | if source.file_id != file_id { | ||
484 | return None; | ||
485 | } | ||
486 | let syntax_node_ptr = | ||
487 | source.ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); | ||
488 | Some((syntax_node_ptr, scope)) | ||
489 | }) | ||
479 | // find containing scope | 490 | // find containing scope |
480 | .min_by_key(|(ptr, _scope)| { | 491 | .min_by_key(|(ptr, _scope)| { |
481 | (!(ptr.range().start() <= offset && offset <= ptr.range().end()), ptr.range().len()) | 492 | (!(ptr.range().start() <= offset && offset <= ptr.range().end()), ptr.range().len()) |
482 | }) | 493 | }) |
483 | .map(|(ptr, scope)| adjust(scopes, source_map, ptr, offset).unwrap_or(*scope)) | 494 | .map(|(ptr, scope)| adjust(scopes, source_map, ptr, file_id, offset).unwrap_or(*scope)) |
484 | } | 495 | } |
485 | 496 | ||
486 | // XXX: during completion, cursor might be outside of any particular | 497 | // XXX: during completion, cursor might be outside of any particular |
@@ -489,13 +500,23 @@ fn adjust( | |||
489 | scopes: &ExprScopes, | 500 | scopes: &ExprScopes, |
490 | source_map: &BodySourceMap, | 501 | source_map: &BodySourceMap, |
491 | ptr: SyntaxNodePtr, | 502 | ptr: SyntaxNodePtr, |
503 | file_id: HirFileId, | ||
492 | offset: TextUnit, | 504 | offset: TextUnit, |
493 | ) -> Option<ScopeId> { | 505 | ) -> Option<ScopeId> { |
494 | let r = ptr.range(); | 506 | let r = ptr.range(); |
495 | let child_scopes = scopes | 507 | let child_scopes = scopes |
496 | .scope_by_expr() | 508 | .scope_by_expr() |
497 | .iter() | 509 | .iter() |
498 | .filter_map(|(id, scope)| Some((source_map.expr_syntax(*id)?, scope))) | 510 | .filter_map(|(id, scope)| { |
511 | let source = source_map.expr_syntax(*id)?; | ||
512 | // FIXME: correctly handle macro expansion | ||
513 | if source.file_id != file_id { | ||
514 | return None; | ||
515 | } | ||
516 | let syntax_node_ptr = | ||
517 | source.ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); | ||
518 | Some((syntax_node_ptr, scope)) | ||
519 | }) | ||
499 | .map(|(ptr, scope)| (ptr.range(), scope)) | 520 | .map(|(ptr, scope)| (ptr.range(), scope)) |
500 | .filter(|(range, _)| range.start() <= offset && range.is_subrange(&r) && *range != r); | 521 | .filter(|(range, _)| range.start() <= offset && range.is_subrange(&r) && *range != r); |
501 | 522 | ||