diff options
Diffstat (limited to 'crates/ra_hir/src/expr.rs')
-rw-r--r-- | crates/ra_hir/src/expr.rs | 93 |
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 | }; |
17 | use crate::{ path::GenericArgs, ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}}; | 17 | use crate::{ path::GenericArgs, ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}}; |
18 | 18 | ||
19 | pub use self::scope::{ExprScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax}; | 19 | pub use self::scope::{ExprScopes, ScopesWithSourceMap, ScopeEntryWithSyntax}; |
20 | 20 | ||
21 | pub(crate) mod scope; | 21 | pub(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)] |
52 | pub struct BodySyntaxMapping { | 52 | pub 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 | ||
60 | impl Body { | 59 | impl 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 | ||
122 | impl BodySyntaxMapping { | 117 | impl 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 | ||
470 | pub(crate) fn body_hir(db: &impl HirDatabase, func: Function) -> Arc<Body> { | ||
471 | Arc::clone(&body_syntax_mapping(db, func).body) | ||
472 | } | ||
473 | |||
474 | struct ExprCollector { | 461 | struct 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 | ||
931 | pub(crate) fn body_syntax_mapping(db: &impl HirDatabase, func: Function) -> Arc<BodySyntaxMapping> { | 908 | pub(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 | |||
921 | pub(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)] |
941 | pub(crate) fn collect_fn_body_syntax(function: Function, node: &ast::FnDef) -> BodySyntaxMapping { | 926 | fn 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 | } |