diff options
author | Aleksey Kladov <[email protected]> | 2019-09-03 09:04:38 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-09-03 09:04:38 +0100 |
commit | 9c3b25177e3c8d609dd24d2c2e01cbb82cab665f (patch) | |
tree | df19e2603745c348e2e5d8289be80c2f511b0b0d /crates/ra_hir/src/source_binder.rs | |
parent | 4b51c92feeda0078033508ceee7345c6ac1a97e6 (diff) |
Correctly build BodySourceMap for macro-expanded expressions
Diffstat (limited to 'crates/ra_hir/src/source_binder.rs')
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 29 |
1 files changed, 22 insertions, 7 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index e5f4d11a6..fdbe5e8b0 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -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 | } |
@@ -470,20 +471,27 @@ fn scope_for( | |||
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)| { | 480 | .filter_map(|(id, scope)| { |
479 | let ast_ptr = source_map.expr_syntax(*id)?.a()?; | 481 | let source = source_map.expr_syntax(*id)?; |
480 | Some((ast_ptr.syntax_node_ptr(), scope)) | 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)) | ||
481 | }) | 489 | }) |
482 | // find containing scope | 490 | // find containing scope |
483 | .min_by_key(|(ptr, _scope)| { | 491 | .min_by_key(|(ptr, _scope)| { |
484 | (!(ptr.range().start() <= offset && offset <= ptr.range().end()), ptr.range().len()) | 492 | (!(ptr.range().start() <= offset && offset <= ptr.range().end()), ptr.range().len()) |
485 | }) | 493 | }) |
486 | .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)) |
487 | } | 495 | } |
488 | 496 | ||
489 | // XXX: during completion, cursor might be outside of any particular | 497 | // XXX: during completion, cursor might be outside of any particular |
@@ -492,6 +500,7 @@ fn adjust( | |||
492 | scopes: &ExprScopes, | 500 | scopes: &ExprScopes, |
493 | source_map: &BodySourceMap, | 501 | source_map: &BodySourceMap, |
494 | ptr: SyntaxNodePtr, | 502 | ptr: SyntaxNodePtr, |
503 | file_id: HirFileId, | ||
495 | offset: TextUnit, | 504 | offset: TextUnit, |
496 | ) -> Option<ScopeId> { | 505 | ) -> Option<ScopeId> { |
497 | let r = ptr.range(); | 506 | let r = ptr.range(); |
@@ -499,8 +508,14 @@ fn adjust( | |||
499 | .scope_by_expr() | 508 | .scope_by_expr() |
500 | .iter() | 509 | .iter() |
501 | .filter_map(|(id, scope)| { | 510 | .filter_map(|(id, scope)| { |
502 | let ast_ptr = source_map.expr_syntax(*id)?.a()?; | 511 | let source = source_map.expr_syntax(*id)?; |
503 | Some((ast_ptr.syntax_node_ptr(), scope)) | 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)) | ||
504 | }) | 519 | }) |
505 | .map(|(ptr, scope)| (ptr.range(), scope)) | 520 | .map(|(ptr, scope)| (ptr.range(), scope)) |
506 | .filter(|(range, _)| range.start() <= offset && range.is_subrange(&r) && *range != r); | 521 | .filter(|(range, _)| range.start() <= offset && range.is_subrange(&r) && *range != r); |