aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/expr.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/expr.rs')
-rw-r--r--crates/ra_hir/src/expr.rs93
1 files changed, 39 insertions, 54 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index aa39d28ed..6c7489e63 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -16,7 +16,7 @@ use crate::{
16}; 16};
17use crate::{ path::GenericArgs, ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}}; 17use crate::{ path::GenericArgs, ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}};
18 18
19pub use self::scope::{ExprScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax}; 19pub use self::scope::{ExprScopes, ScopesWithSourceMap, ScopeEntryWithSyntax};
20 20
21pub(crate) mod scope; 21pub(crate) mod scope;
22 22
@@ -48,13 +48,12 @@ pub struct Body {
48/// expression containing it; but for type inference etc., we want to operate on 48/// expression containing it; but for type inference etc., we want to operate on
49/// a structure that is agnostic to the actual positions of expressions in the 49/// a structure that is agnostic to the actual positions of expressions in the
50/// file, so that we don't recompute types whenever some whitespace is typed. 50/// file, so that we don't recompute types whenever some whitespace is typed.
51#[derive(Debug, Eq, PartialEq)] 51#[derive(Default, Debug, Eq, PartialEq)]
52pub struct BodySyntaxMapping { 52pub struct BodySourceMap {
53 body: Arc<Body>, 53 expr_map: FxHashMap<SyntaxNodePtr, ExprId>,
54 expr_syntax_mapping: FxHashMap<SyntaxNodePtr, ExprId>, 54 expr_map_back: ArenaMap<ExprId, SyntaxNodePtr>,
55 expr_syntax_mapping_back: ArenaMap<ExprId, SyntaxNodePtr>, 55 pat_map: FxHashMap<SyntaxNodePtr, PatId>,
56 pat_syntax_mapping: FxHashMap<SyntaxNodePtr, PatId>, 56 pat_map_back: ArenaMap<PatId, SyntaxNodePtr>,
57 pat_syntax_mapping_back: ArenaMap<PatId, SyntaxNodePtr>,
58} 57}
59 58
60impl Body { 59impl Body {
@@ -77,10 +76,6 @@ impl Body {
77 pub fn pats(&self) -> impl Iterator<Item = (PatId, &Pat)> { 76 pub fn pats(&self) -> impl Iterator<Item = (PatId, &Pat)> {
78 self.pats.iter() 77 self.pats.iter()
79 } 78 }
80
81 pub fn syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> {
82 db.body_syntax_mapping(self.owner)
83 }
84} 79}
85 80
86// needs arbitrary_self_types to be a method... or maybe move to the def? 81// needs arbitrary_self_types to be a method... or maybe move to the def?
@@ -119,33 +114,29 @@ impl Index<PatId> for Body {
119 } 114 }
120} 115}
121 116
122impl BodySyntaxMapping { 117impl BodySourceMap {
123 pub fn expr_syntax(&self, expr: ExprId) -> Option<SyntaxNodePtr> { 118 pub fn expr_syntax(&self, expr: ExprId) -> Option<SyntaxNodePtr> {
124 self.expr_syntax_mapping_back.get(expr).cloned() 119 self.expr_map_back.get(expr).cloned()
125 } 120 }
126 121
127 pub fn syntax_expr(&self, ptr: SyntaxNodePtr) -> Option<ExprId> { 122 pub fn syntax_expr(&self, ptr: SyntaxNodePtr) -> Option<ExprId> {
128 self.expr_syntax_mapping.get(&ptr).cloned() 123 self.expr_map.get(&ptr).cloned()
129 } 124 }
130 125
131 pub fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> { 126 pub fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> {
132 self.expr_syntax_mapping.get(&SyntaxNodePtr::new(node.syntax())).cloned() 127 self.expr_map.get(&SyntaxNodePtr::new(node.syntax())).cloned()
133 } 128 }
134 129
135 pub fn pat_syntax(&self, pat: PatId) -> Option<SyntaxNodePtr> { 130 pub fn pat_syntax(&self, pat: PatId) -> Option<SyntaxNodePtr> {
136 self.pat_syntax_mapping_back.get(pat).cloned() 131 self.pat_map_back.get(pat).cloned()
137 } 132 }
138 133
139 pub fn syntax_pat(&self, ptr: SyntaxNodePtr) -> Option<PatId> { 134 pub fn syntax_pat(&self, ptr: SyntaxNodePtr) -> Option<PatId> {
140 self.pat_syntax_mapping.get(&ptr).cloned() 135 self.pat_map.get(&ptr).cloned()
141 } 136 }
142 137
143 pub fn node_pat(&self, node: &ast::Pat) -> Option<PatId> { 138 pub fn node_pat(&self, node: &ast::Pat) -> Option<PatId> {
144 self.pat_syntax_mapping.get(&SyntaxNodePtr::new(node.syntax())).cloned() 139 self.pat_map.get(&SyntaxNodePtr::new(node.syntax())).cloned()
145 }
146
147 pub fn body(&self) -> &Arc<Body> {
148 &self.body
149 } 140 }
150} 141}
151 142
@@ -467,18 +458,11 @@ impl Pat {
467 458
468// Queries 459// Queries
469 460
470pub(crate) fn body_hir(db: &impl HirDatabase, func: Function) -> Arc<Body> {
471 Arc::clone(&body_syntax_mapping(db, func).body)
472}
473
474struct ExprCollector { 461struct ExprCollector {
475 owner: Function, 462 owner: Function,
476 exprs: Arena<ExprId, Expr>, 463 exprs: Arena<ExprId, Expr>,
477 pats: Arena<PatId, Pat>, 464 pats: Arena<PatId, Pat>,
478 expr_syntax_mapping: FxHashMap<SyntaxNodePtr, ExprId>, 465 source_map: BodySourceMap,
479 expr_syntax_mapping_back: ArenaMap<ExprId, SyntaxNodePtr>,
480 pat_syntax_mapping: FxHashMap<SyntaxNodePtr, PatId>,
481 pat_syntax_mapping_back: ArenaMap<PatId, SyntaxNodePtr>,
482 params: Vec<PatId>, 466 params: Vec<PatId>,
483 body_expr: Option<ExprId>, 467 body_expr: Option<ExprId>,
484} 468}
@@ -489,10 +473,7 @@ impl ExprCollector {
489 owner, 473 owner,
490 exprs: Arena::default(), 474 exprs: Arena::default(),
491 pats: Arena::default(), 475 pats: Arena::default(),
492 expr_syntax_mapping: FxHashMap::default(), 476 source_map: BodySourceMap::default(),
493 expr_syntax_mapping_back: ArenaMap::default(),
494 pat_syntax_mapping: FxHashMap::default(),
495 pat_syntax_mapping_back: ArenaMap::default(),
496 params: Vec::new(), 477 params: Vec::new(),
497 body_expr: None, 478 body_expr: None,
498 } 479 }
@@ -500,15 +481,15 @@ impl ExprCollector {
500 481
501 fn alloc_expr(&mut self, expr: Expr, syntax_ptr: SyntaxNodePtr) -> ExprId { 482 fn alloc_expr(&mut self, expr: Expr, syntax_ptr: SyntaxNodePtr) -> ExprId {
502 let id = self.exprs.alloc(expr); 483 let id = self.exprs.alloc(expr);
503 self.expr_syntax_mapping.insert(syntax_ptr, id); 484 self.source_map.expr_map.insert(syntax_ptr, id);
504 self.expr_syntax_mapping_back.insert(id, syntax_ptr); 485 self.source_map.expr_map_back.insert(id, syntax_ptr);
505 id 486 id
506 } 487 }
507 488
508 fn alloc_pat(&mut self, pat: Pat, syntax_ptr: SyntaxNodePtr) -> PatId { 489 fn alloc_pat(&mut self, pat: Pat, syntax_ptr: SyntaxNodePtr) -> PatId {
509 let id = self.pats.alloc(pat); 490 let id = self.pats.alloc(pat);
510 self.pat_syntax_mapping.insert(syntax_ptr, id); 491 self.source_map.pat_map.insert(syntax_ptr, id);
511 self.pat_syntax_mapping_back.insert(id, syntax_ptr); 492 self.source_map.pat_map_back.insert(id, syntax_ptr);
512 id 493 id
513 } 494 }
514 495
@@ -639,7 +620,7 @@ impl ExprCollector {
639 ast::ExprKind::ParenExpr(e) => { 620 ast::ExprKind::ParenExpr(e) => {
640 let inner = self.collect_expr_opt(e.expr()); 621 let inner = self.collect_expr_opt(e.expr());
641 // make the paren expr point to the inner expression as well 622 // make the paren expr point to the inner expression as well
642 self.expr_syntax_mapping.insert(syntax_ptr, inner); 623 self.source_map.expr_map.insert(syntax_ptr, inner);
643 inner 624 inner
644 } 625 }
645 ast::ExprKind::ReturnExpr(e) => { 626 ast::ExprKind::ReturnExpr(e) => {
@@ -660,9 +641,11 @@ impl ExprCollector {
660 } else if let Some(nr) = field.name_ref() { 641 } else if let Some(nr) = field.name_ref() {
661 // field shorthand 642 // field shorthand
662 let id = self.exprs.alloc(Expr::Path(Path::from_name_ref(nr))); 643 let id = self.exprs.alloc(Expr::Path(Path::from_name_ref(nr)));
663 self.expr_syntax_mapping 644 self.source_map
645 .expr_map
664 .insert(SyntaxNodePtr::new(nr.syntax()), id); 646 .insert(SyntaxNodePtr::new(nr.syntax()), id);
665 self.expr_syntax_mapping_back 647 self.source_map
648 .expr_map_back
666 .insert(id, SyntaxNodePtr::new(nr.syntax())); 649 .insert(id, SyntaxNodePtr::new(nr.syntax()));
667 id 650 id
668 } else { 651 } else {
@@ -910,7 +893,7 @@ impl ExprCollector {
910 self.body_expr = Some(body); 893 self.body_expr = Some(body);
911 } 894 }
912 895
913 fn into_body_syntax_mapping(self) -> BodySyntaxMapping { 896 fn finish(self) -> (Body, BodySourceMap) {
914 let body = Body { 897 let body = Body {
915 owner: self.owner, 898 owner: self.owner,
916 exprs: self.exprs, 899 exprs: self.exprs,
@@ -918,28 +901,30 @@ impl ExprCollector {
918 params: self.params, 901 params: self.params,
919 body_expr: self.body_expr.expect("A body should have been collected"), 902 body_expr: self.body_expr.expect("A body should have been collected"),
920 }; 903 };
921 BodySyntaxMapping { 904 (body, self.source_map)
922 body: Arc::new(body),
923 expr_syntax_mapping: self.expr_syntax_mapping,
924 expr_syntax_mapping_back: self.expr_syntax_mapping_back,
925 pat_syntax_mapping: self.pat_syntax_mapping,
926 pat_syntax_mapping_back: self.pat_syntax_mapping_back,
927 }
928 } 905 }
929} 906}
930 907
931pub(crate) fn body_syntax_mapping(db: &impl HirDatabase, func: Function) -> Arc<BodySyntaxMapping> { 908pub(crate) fn body_with_source_map_query(
909 db: &impl HirDatabase,
910 func: Function,
911) -> (Arc<Body>, Arc<BodySourceMap>) {
932 let mut collector = ExprCollector::new(func); 912 let mut collector = ExprCollector::new(func);
933 913
934 // TODO: consts, etc. 914 // TODO: consts, etc.
935 collector.collect_fn_body(&func.source(db).1); 915 collector.collect_fn_body(&func.source(db).1);
936 916
937 Arc::new(collector.into_body_syntax_mapping()) 917 let (body, source_map) = collector.finish();
918 (Arc::new(body), Arc::new(source_map))
919}
920
921pub(crate) fn body_hir_query(db: &impl HirDatabase, func: Function) -> Arc<Body> {
922 db.body_with_source_map(func).0
938} 923}
939 924
940#[cfg(test)] 925#[cfg(test)]
941pub(crate) fn collect_fn_body_syntax(function: Function, node: &ast::FnDef) -> BodySyntaxMapping { 926fn collect_fn_body_syntax(function: Function, node: &ast::FnDef) -> (Body, BodySourceMap) {
942 let mut collector = ExprCollector::new(function); 927 let mut collector = ExprCollector::new(function);
943 collector.collect_fn_body(node); 928 collector.collect_fn_body(node);
944 collector.into_body_syntax_mapping() 929 collector.finish()
945} 930}