aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/code_model/src.rs6
-rw-r--r--crates/ra_hir/src/expr.rs52
-rw-r--r--crates/ra_hir/src/expr/scope.rs5
-rw-r--r--crates/ra_hir/src/expr/validation.rs13
-rw-r--r--crates/ra_hir/src/source_binder.rs14
-rw-r--r--crates/ra_hir/src/ty/tests.rs2
6 files changed, 50 insertions, 42 deletions
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs
index e5bae16ab..7c9454c0b 100644
--- a/crates/ra_hir/src/code_model/src.rs
+++ b/crates/ra_hir/src/code_model/src.rs
@@ -119,10 +119,10 @@ where
119 expr_id: crate::expr::ExprId, 119 expr_id: crate::expr::ExprId,
120 ) -> Option<Source<ast::Expr>> { 120 ) -> Option<Source<ast::Expr>> {
121 let source_map = self.body_source_map(db); 121 let source_map = self.body_source_map(db);
122 let expr_syntax = source_map.expr_syntax(expr_id)?; 122 let expr_syntax = source_map.expr_syntax(expr_id)?.a()?;
123 let source = self.source(db); 123 let source = self.source(db);
124 let node = expr_syntax.to_node(&source.ast.syntax()); 124 let ast = expr_syntax.to_node(&source.ast.syntax());
125 ast::Expr::cast(node).map(|ast| Source { file_id: source.file_id, ast }) 125 Some(Source { file_id: source.file_id, ast })
126 } 126 }
127} 127}
128 128
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index c7530849b..5c95bed40 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -9,7 +9,7 @@ use ra_syntax::{
9 self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, NameOwner, 9 self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, NameOwner,
10 TypeAscriptionOwner, 10 TypeAscriptionOwner,
11 }, 11 },
12 AstNode, AstPtr, SyntaxNodePtr, 12 AstNode, AstPtr,
13}; 13};
14use test_utils::tested_by; 14use test_utils::tested_by;
15 15
@@ -56,13 +56,14 @@ pub struct Body {
56/// file, so that we don't recompute types whenever some whitespace is typed. 56/// file, so that we don't recompute types whenever some whitespace is typed.
57#[derive(Default, Debug, Eq, PartialEq)] 57#[derive(Default, Debug, Eq, PartialEq)]
58pub struct BodySourceMap { 58pub struct BodySourceMap {
59 expr_map: FxHashMap<SyntaxNodePtr, ExprId>, 59 expr_map: FxHashMap<ExprPtr, ExprId>,
60 expr_map_back: ArenaMap<ExprId, SyntaxNodePtr>, 60 expr_map_back: ArenaMap<ExprId, ExprPtr>,
61 pat_map: FxHashMap<PatPtr, PatId>, 61 pat_map: FxHashMap<PatPtr, PatId>,
62 pat_map_back: ArenaMap<PatId, PatPtr>, 62 pat_map_back: ArenaMap<PatId, PatPtr>,
63 field_map: FxHashMap<(ExprId, usize), AstPtr<ast::RecordField>>, 63 field_map: FxHashMap<(ExprId, usize), AstPtr<ast::RecordField>>,
64} 64}
65 65
66type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>;
66type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>; 67type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>;
67 68
68impl Body { 69impl Body {
@@ -128,16 +129,12 @@ impl Index<PatId> for Body {
128} 129}
129 130
130impl BodySourceMap { 131impl BodySourceMap {
131 pub(crate) fn expr_syntax(&self, expr: ExprId) -> Option<SyntaxNodePtr> { 132 pub(crate) fn expr_syntax(&self, expr: ExprId) -> Option<ExprPtr> {
132 self.expr_map_back.get(expr).cloned() 133 self.expr_map_back.get(expr).cloned()
133 } 134 }
134 135
135 pub(crate) fn syntax_expr(&self, ptr: SyntaxNodePtr) -> Option<ExprId> {
136 self.expr_map.get(&ptr).cloned()
137 }
138
139 pub(crate) fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> { 136 pub(crate) fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> {
140 self.expr_map.get(&SyntaxNodePtr::new(node.syntax())).cloned() 137 self.expr_map.get(&Either::A(AstPtr::new(node))).cloned()
141 } 138 }
142 139
143 pub(crate) fn pat_syntax(&self, pat: PatId) -> Option<PatPtr> { 140 pub(crate) fn pat_syntax(&self, pat: PatId) -> Option<PatPtr> {
@@ -575,11 +572,12 @@ where
575 current_file_id: file_id, 572 current_file_id: file_id,
576 } 573 }
577 } 574 }
578 fn alloc_expr(&mut self, expr: Expr, syntax_ptr: SyntaxNodePtr) -> ExprId { 575 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId {
576 let ptr = Either::A(ptr);
579 let id = self.exprs.alloc(expr); 577 let id = self.exprs.alloc(expr);
580 if self.current_file_id == self.original_file_id { 578 if self.current_file_id == self.original_file_id {
581 self.source_map.expr_map.insert(syntax_ptr, id); 579 self.source_map.expr_map.insert(ptr, id);
582 self.source_map.expr_map_back.insert(id, syntax_ptr); 580 self.source_map.expr_map_back.insert(id, ptr);
583 } 581 }
584 id 582 id
585 } 583 }
@@ -601,7 +599,7 @@ where
601 } 599 }
602 600
603 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { 601 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
604 let syntax_ptr = SyntaxNodePtr::new(expr.syntax()); 602 let syntax_ptr = AstPtr::new(&expr);
605 match expr { 603 match expr {
606 ast::Expr::IfExpr(e) => { 604 ast::Expr::IfExpr(e) => {
607 let then_branch = self.collect_block_opt(e.then_branch()); 605 let then_branch = self.collect_block_opt(e.then_branch());
@@ -640,10 +638,10 @@ where
640 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr) 638 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
641 } 639 }
642 ast::Expr::TryBlockExpr(e) => { 640 ast::Expr::TryBlockExpr(e) => {
643 let body = self.collect_block_opt(e.block()); 641 let body = self.collect_block_opt(e.body());
644 self.alloc_expr(Expr::TryBlock { body }, syntax_ptr) 642 self.alloc_expr(Expr::TryBlock { body }, syntax_ptr)
645 } 643 }
646 ast::Expr::BlockExpr(e) => self.collect_block_opt(e.block()), 644 ast::Expr::BlockExpr(e) => self.collect_block(e),
647 ast::Expr::LoopExpr(e) => { 645 ast::Expr::LoopExpr(e) => {
648 let body = self.collect_block_opt(e.loop_body()); 646 let body = self.collect_block_opt(e.loop_body());
649 self.alloc_expr(Expr::Loop { body }, syntax_ptr) 647 self.alloc_expr(Expr::Loop { body }, syntax_ptr)
@@ -739,7 +737,7 @@ where
739 ast::Expr::ParenExpr(e) => { 737 ast::Expr::ParenExpr(e) => {
740 let inner = self.collect_expr_opt(e.expr()); 738 let inner = self.collect_expr_opt(e.expr());
741 // make the paren expr point to the inner expression as well 739 // make the paren expr point to the inner expression as well
742 self.source_map.expr_map.insert(syntax_ptr, inner); 740 self.source_map.expr_map.insert(Either::A(syntax_ptr), inner);
743 inner 741 inner
744 } 742 }
745 ast::Expr::ReturnExpr(e) => { 743 ast::Expr::ReturnExpr(e) => {
@@ -763,12 +761,9 @@ where
763 } else if let Some(nr) = field.name_ref() { 761 } else if let Some(nr) = field.name_ref() {
764 // field shorthand 762 // field shorthand
765 let id = self.exprs.alloc(Expr::Path(Path::from_name_ref(&nr))); 763 let id = self.exprs.alloc(Expr::Path(Path::from_name_ref(&nr)));
766 self.source_map 764 let ptr = Either::B(AstPtr::new(&field));
767 .expr_map 765 self.source_map.expr_map.insert(ptr, id);
768 .insert(SyntaxNodePtr::new(nr.syntax()), id); 766 self.source_map.expr_map_back.insert(id, ptr);
769 self.source_map
770 .expr_map_back
771 .insert(id, SyntaxNodePtr::new(nr.syntax()));
772 id 767 id
773 } else { 768 } else {
774 self.exprs.alloc(Expr::Missing) 769 self.exprs.alloc(Expr::Missing)
@@ -942,7 +937,12 @@ where
942 } 937 }
943 } 938 }
944 939
945 fn collect_block(&mut self, block: ast::Block) -> ExprId { 940 fn collect_block(&mut self, expr: ast::BlockExpr) -> ExprId {
941 let syntax_node_ptr = AstPtr::new(&expr.clone().into());
942 let block = match expr.block() {
943 Some(block) => block,
944 None => return self.alloc_expr(Expr::Missing, syntax_node_ptr),
945 };
946 let statements = block 946 let statements = block
947 .statements() 947 .statements()
948 .map(|s| match s { 948 .map(|s| match s {
@@ -956,11 +956,11 @@ where
956 }) 956 })
957 .collect(); 957 .collect();
958 let tail = block.expr().map(|e| self.collect_expr(e)); 958 let tail = block.expr().map(|e| self.collect_expr(e));
959 self.alloc_expr(Expr::Block { statements, tail }, SyntaxNodePtr::new(block.syntax())) 959 self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr)
960 } 960 }
961 961
962 fn collect_block_opt(&mut self, block: Option<ast::Block>) -> ExprId { 962 fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId {
963 if let Some(block) = block { 963 if let Some(block) = expr {
964 self.collect_block(block) 964 self.collect_block(block)
965 } else { 965 } else {
966 self.exprs.alloc(Expr::Missing) 966 self.exprs.alloc(Expr::Missing)
diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs
index 79e1857f9..b6d7f3fc1 100644
--- a/crates/ra_hir/src/expr/scope.rs
+++ b/crates/ra_hir/src/expr/scope.rs
@@ -172,7 +172,7 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
172#[cfg(test)] 172#[cfg(test)]
173mod tests { 173mod tests {
174 use ra_db::SourceDatabase; 174 use ra_db::SourceDatabase;
175 use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SyntaxNodePtr}; 175 use ra_syntax::{algo::find_node_at_offset, ast, AstNode};
176 use test_utils::{assert_eq_text, extract_offset}; 176 use test_utils::{assert_eq_text, extract_offset};
177 177
178 use crate::{mock::MockDatabase, source_binder::SourceAnalyzer}; 178 use crate::{mock::MockDatabase, source_binder::SourceAnalyzer};
@@ -194,8 +194,7 @@ mod tests {
194 let analyzer = SourceAnalyzer::new(&db, file_id, marker.syntax(), None); 194 let analyzer = SourceAnalyzer::new(&db, file_id, marker.syntax(), None);
195 195
196 let scopes = analyzer.scopes(); 196 let scopes = analyzer.scopes();
197 let expr_id = 197 let expr_id = analyzer.body_source_map().node_expr(&marker.into()).unwrap();
198 analyzer.body_source_map().syntax_expr(SyntaxNodePtr::new(marker.syntax())).unwrap();
199 let scope = scopes.scope_for(expr_id); 198 let scope = scopes.scope_for(expr_id);
200 199
201 let actual = scopes 200 let actual = scopes
diff --git a/crates/ra_hir/src/expr/validation.rs b/crates/ra_hir/src/expr/validation.rs
index c8ae19869..6fdaf1fce 100644
--- a/crates/ra_hir/src/expr/validation.rs
+++ b/crates/ra_hir/src/expr/validation.rs
@@ -1,7 +1,7 @@
1use rustc_hash::FxHashSet;
2use std::sync::Arc; 1use std::sync::Arc;
3 2
4use ra_syntax::ast::{AstNode, RecordLit}; 3use ra_syntax::ast::{self, AstNode};
4use rustc_hash::FxHashSet;
5 5
6use super::{Expr, ExprId, RecordLitField}; 6use super::{Expr, ExprId, RecordLitField};
7use crate::{ 7use crate::{
@@ -13,7 +13,6 @@ use crate::{
13 ty::{ApplicationTy, InferenceResult, Ty, TypeCtor}, 13 ty::{ApplicationTy, InferenceResult, Ty, TypeCtor},
14 Function, HasSource, HirDatabase, ModuleDef, Name, Path, PerNs, Resolution, 14 Function, HasSource, HirDatabase, ModuleDef, Name, Path, PerNs, Resolution,
15}; 15};
16use ra_syntax::ast;
17 16
18pub(crate) struct ExprValidator<'a, 'b: 'a> { 17pub(crate) struct ExprValidator<'a, 'b: 'a> {
19 func: Function, 18 func: Function,
@@ -84,8 +83,12 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
84 let source_file = parse.tree(); 83 let source_file = parse.tree();
85 if let Some(field_list_node) = source_map 84 if let Some(field_list_node) = source_map
86 .expr_syntax(id) 85 .expr_syntax(id)
86 .and_then(|ptr| ptr.a())
87 .map(|ptr| ptr.to_node(source_file.syntax())) 87 .map(|ptr| ptr.to_node(source_file.syntax()))
88 .and_then(RecordLit::cast) 88 .and_then(|expr| match expr {
89 ast::Expr::RecordLit(it) => Some(it),
90 _ => None,
91 })
89 .and_then(|lit| lit.record_field_list()) 92 .and_then(|lit| lit.record_field_list())
90 { 93 {
91 let field_list_ptr = AstPtr::new(&field_list_node); 94 let field_list_ptr = AstPtr::new(&field_list_node);
@@ -135,7 +138,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
135 let source_map = self.func.body_source_map(db); 138 let source_map = self.func.body_source_map(db);
136 let file_id = self.func.source(db).file_id; 139 let file_id = self.func.source(db).file_id;
137 140
138 if let Some(expr) = source_map.expr_syntax(id).and_then(|n| n.cast::<ast::Expr>()) { 141 if let Some(expr) = source_map.expr_syntax(id).and_then(|n| n.a()) {
139 self.sink.push(MissingOkInTailExpr { file: file_id, expr }); 142 self.sink.push(MissingOkInTailExpr { file: file_id, expr });
140 } 143 }
141 } 144 }
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 43aec201a..e5f4d11a6 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -462,8 +462,8 @@ fn scope_for(
462 node: &SyntaxNode, 462 node: &SyntaxNode,
463) -> Option<ScopeId> { 463) -> Option<ScopeId> {
464 node.ancestors() 464 node.ancestors()
465 .map(|it| SyntaxNodePtr::new(&it)) 465 .filter_map(ast::Expr::cast)
466 .filter_map(|ptr| source_map.syntax_expr(ptr)) 466 .filter_map(|it| source_map.node_expr(&it))
467 .find_map(|it| scopes.scope_for(it)) 467 .find_map(|it| scopes.scope_for(it))
468} 468}
469 469
@@ -475,7 +475,10 @@ fn scope_for_offset(
475 scopes 475 scopes
476 .scope_by_expr() 476 .scope_by_expr()
477 .iter() 477 .iter()
478 .filter_map(|(id, scope)| Some((source_map.expr_syntax(*id)?, scope))) 478 .filter_map(|(id, scope)| {
479 let ast_ptr = source_map.expr_syntax(*id)?.a()?;
480 Some((ast_ptr.syntax_node_ptr(), scope))
481 })
479 // find containing scope 482 // find containing scope
480 .min_by_key(|(ptr, _scope)| { 483 .min_by_key(|(ptr, _scope)| {
481 (!(ptr.range().start() <= offset && offset <= ptr.range().end()), ptr.range().len()) 484 (!(ptr.range().start() <= offset && offset <= ptr.range().end()), ptr.range().len())
@@ -495,7 +498,10 @@ fn adjust(
495 let child_scopes = scopes 498 let child_scopes = scopes
496 .scope_by_expr() 499 .scope_by_expr()
497 .iter() 500 .iter()
498 .filter_map(|(id, scope)| Some((source_map.expr_syntax(*id)?, scope))) 501 .filter_map(|(id, scope)| {
502 let ast_ptr = source_map.expr_syntax(*id)?.a()?;
503 Some((ast_ptr.syntax_node_ptr(), scope))
504 })
499 .map(|(ptr, scope)| (ptr.range(), scope)) 505 .map(|(ptr, scope)| (ptr.range(), scope))
500 .filter(|(range, _)| range.start() <= offset && range.is_subrange(&r) && *range != r); 506 .filter(|(range, _)| range.start() <= offset && range.is_subrange(&r) && *range != r);
501 507
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index b034fd59e..d344ab12e 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -3582,7 +3582,7 @@ fn infer(content: &str) -> String {
3582 3582
3583 for (expr, ty) in inference_result.type_of_expr.iter() { 3583 for (expr, ty) in inference_result.type_of_expr.iter() {
3584 let syntax_ptr = match body_source_map.expr_syntax(expr) { 3584 let syntax_ptr = match body_source_map.expr_syntax(expr) {
3585 Some(sp) => sp, 3585 Some(sp) => sp.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()),
3586 None => continue, 3586 None => continue,
3587 }; 3587 };
3588 types.push((syntax_ptr, ty)); 3588 types.push((syntax_ptr, ty));