diff options
Diffstat (limited to 'crates/ra_hir/src/expr.rs')
-rw-r--r-- | crates/ra_hir/src/expr.rs | 129 |
1 files changed, 77 insertions, 52 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 6d124fe2f..c09d3fbf9 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -27,6 +27,9 @@ impl_arena_id!(ExprId); | |||
27 | /// The body of an item (function, const etc.). | 27 | /// The body of an item (function, const etc.). |
28 | #[derive(Debug, Eq, PartialEq)] | 28 | #[derive(Debug, Eq, PartialEq)] |
29 | pub struct Body { | 29 | pub struct Body { |
30 | // TODO: this should be more general, consts & statics also have bodies | ||
31 | /// The Function of the item this body belongs to | ||
32 | owner: Function, | ||
30 | exprs: Arena<ExprId, Expr>, | 33 | exprs: Arena<ExprId, Expr>, |
31 | pats: Arena<PatId, Pat>, | 34 | pats: Arena<PatId, Pat>, |
32 | /// The patterns for the function's parameters. While the parameter types are | 35 | /// The patterns for the function's parameters. While the parameter types are |
@@ -63,12 +66,26 @@ impl Body { | |||
63 | self.body_expr | 66 | self.body_expr |
64 | } | 67 | } |
65 | 68 | ||
66 | #[allow(unused_variables)] | 69 | pub fn owner(&self) -> Function { |
67 | pub fn resolver_for_expr(&self, expr_id: ExprId) -> Resolver { | 70 | self.owner |
68 | unimplemented!() | ||
69 | } | 71 | } |
70 | } | 72 | } |
71 | 73 | ||
74 | // needs arbitrary_self_types to be a method... or maybe move to the def? | ||
75 | #[allow(dead_code)] | ||
76 | pub fn resolver_for_expr(body: Arc<Body>, db: &impl HirDatabase, expr_id: ExprId) -> Resolver { | ||
77 | let mut r = body.owner.resolver(db); | ||
78 | if !body.params.is_empty() { | ||
79 | r = r.push_function_params(Arc::clone(&body)); | ||
80 | } | ||
81 | let scopes = db.expr_scopes(body.owner); | ||
82 | let scope_chain = scopes.scope_chain_for(expr_id).collect::<Vec<_>>(); | ||
83 | for scope in scope_chain.into_iter().rev() { | ||
84 | r = r.push_expr_scope(Arc::clone(&scopes), scope); | ||
85 | } | ||
86 | r | ||
87 | } | ||
88 | |||
72 | impl Index<ExprId> for Body { | 89 | impl Index<ExprId> for Body { |
73 | type Output = Expr; | 90 | type Output = Expr; |
74 | 91 | ||
@@ -453,23 +470,29 @@ pub(crate) fn body_hir(db: &impl HirDatabase, func: Function) -> Arc<Body> { | |||
453 | } | 470 | } |
454 | 471 | ||
455 | struct ExprCollector { | 472 | struct ExprCollector { |
473 | owner: Function, | ||
456 | exprs: Arena<ExprId, Expr>, | 474 | exprs: Arena<ExprId, Expr>, |
457 | pats: Arena<PatId, Pat>, | 475 | pats: Arena<PatId, Pat>, |
458 | expr_syntax_mapping: FxHashMap<SyntaxNodePtr, ExprId>, | 476 | expr_syntax_mapping: FxHashMap<SyntaxNodePtr, ExprId>, |
459 | expr_syntax_mapping_back: ArenaMap<ExprId, SyntaxNodePtr>, | 477 | expr_syntax_mapping_back: ArenaMap<ExprId, SyntaxNodePtr>, |
460 | pat_syntax_mapping: FxHashMap<SyntaxNodePtr, PatId>, | 478 | pat_syntax_mapping: FxHashMap<SyntaxNodePtr, PatId>, |
461 | pat_syntax_mapping_back: ArenaMap<PatId, SyntaxNodePtr>, | 479 | pat_syntax_mapping_back: ArenaMap<PatId, SyntaxNodePtr>, |
480 | params: Vec<PatId>, | ||
481 | body_expr: Option<ExprId>, | ||
462 | } | 482 | } |
463 | 483 | ||
464 | impl ExprCollector { | 484 | impl ExprCollector { |
465 | fn new() -> Self { | 485 | fn new(owner: Function) -> Self { |
466 | ExprCollector { | 486 | ExprCollector { |
487 | owner, | ||
467 | exprs: Arena::default(), | 488 | exprs: Arena::default(), |
468 | pats: Arena::default(), | 489 | pats: Arena::default(), |
469 | expr_syntax_mapping: FxHashMap::default(), | 490 | expr_syntax_mapping: FxHashMap::default(), |
470 | expr_syntax_mapping_back: ArenaMap::default(), | 491 | expr_syntax_mapping_back: ArenaMap::default(), |
471 | pat_syntax_mapping: FxHashMap::default(), | 492 | pat_syntax_mapping: FxHashMap::default(), |
472 | pat_syntax_mapping_back: ArenaMap::default(), | 493 | pat_syntax_mapping_back: ArenaMap::default(), |
494 | params: Vec::new(), | ||
495 | body_expr: None, | ||
473 | } | 496 | } |
474 | } | 497 | } |
475 | 498 | ||
@@ -907,10 +930,7 @@ impl ExprCollector { | |||
907 | }); | 930 | }); |
908 | fields.extend(iter); | 931 | fields.extend(iter); |
909 | 932 | ||
910 | Pat::Struct { | 933 | Pat::Struct { path, args: fields } |
911 | path: path, | ||
912 | args: fields, | ||
913 | } | ||
914 | } | 934 | } |
915 | 935 | ||
916 | // TODO: implement | 936 | // TODO: implement |
@@ -928,12 +948,48 @@ impl ExprCollector { | |||
928 | } | 948 | } |
929 | } | 949 | } |
930 | 950 | ||
931 | fn into_body_syntax_mapping(self, params: Vec<PatId>, body_expr: ExprId) -> BodySyntaxMapping { | 951 | fn collect_fn_body(&mut self, node: &ast::FnDef) { |
952 | if let Some(param_list) = node.param_list() { | ||
953 | if let Some(self_param) = param_list.self_param() { | ||
954 | let self_param = SyntaxNodePtr::new( | ||
955 | self_param | ||
956 | .self_kw() | ||
957 | .expect("self param without self keyword") | ||
958 | .syntax(), | ||
959 | ); | ||
960 | let param_pat = self.alloc_pat( | ||
961 | Pat::Bind { | ||
962 | name: Name::self_param(), | ||
963 | mode: BindingAnnotation::Unannotated, | ||
964 | subpat: None, | ||
965 | }, | ||
966 | self_param, | ||
967 | ); | ||
968 | self.params.push(param_pat); | ||
969 | } | ||
970 | |||
971 | for param in param_list.params() { | ||
972 | let pat = if let Some(pat) = param.pat() { | ||
973 | pat | ||
974 | } else { | ||
975 | continue; | ||
976 | }; | ||
977 | let param_pat = self.collect_pat(pat); | ||
978 | self.params.push(param_pat); | ||
979 | } | ||
980 | }; | ||
981 | |||
982 | let body = self.collect_block_opt(node.body()); | ||
983 | self.body_expr = Some(body); | ||
984 | } | ||
985 | |||
986 | fn into_body_syntax_mapping(self) -> BodySyntaxMapping { | ||
932 | let body = Body { | 987 | let body = Body { |
988 | owner: self.owner, | ||
933 | exprs: self.exprs, | 989 | exprs: self.exprs, |
934 | pats: self.pats, | 990 | pats: self.pats, |
935 | params, | 991 | params: self.params, |
936 | body_expr, | 992 | body_expr: self.body_expr.expect("A body should have been collected"), |
937 | }; | 993 | }; |
938 | BodySyntaxMapping { | 994 | BodySyntaxMapping { |
939 | body: Arc::new(body), | 995 | body: Arc::new(body), |
@@ -945,49 +1001,18 @@ impl ExprCollector { | |||
945 | } | 1001 | } |
946 | } | 1002 | } |
947 | 1003 | ||
948 | pub(crate) fn collect_fn_body_syntax(node: &ast::FnDef) -> BodySyntaxMapping { | 1004 | pub(crate) fn body_syntax_mapping(db: &impl HirDatabase, func: Function) -> Arc<BodySyntaxMapping> { |
949 | let mut collector = ExprCollector::new(); | 1005 | let mut collector = ExprCollector::new(func); |
950 | |||
951 | let params = if let Some(param_list) = node.param_list() { | ||
952 | let mut params = Vec::new(); | ||
953 | |||
954 | if let Some(self_param) = param_list.self_param() { | ||
955 | let self_param = SyntaxNodePtr::new( | ||
956 | self_param | ||
957 | .self_kw() | ||
958 | .expect("self param without self keyword") | ||
959 | .syntax(), | ||
960 | ); | ||
961 | let param = collector.alloc_pat( | ||
962 | Pat::Bind { | ||
963 | name: Name::self_param(), | ||
964 | mode: BindingAnnotation::Unannotated, | ||
965 | subpat: None, | ||
966 | }, | ||
967 | self_param, | ||
968 | ); | ||
969 | params.push(param); | ||
970 | } | ||
971 | 1006 | ||
972 | for param in param_list.params() { | 1007 | // TODO: consts, etc. |
973 | let pat = if let Some(pat) = param.pat() { | 1008 | collector.collect_fn_body(&func.source(db).1); |
974 | pat | ||
975 | } else { | ||
976 | continue; | ||
977 | }; | ||
978 | params.push(collector.collect_pat(pat)); | ||
979 | } | ||
980 | params | ||
981 | } else { | ||
982 | Vec::new() | ||
983 | }; | ||
984 | 1009 | ||
985 | let body = collector.collect_block_opt(node.body()); | 1010 | Arc::new(collector.into_body_syntax_mapping()) |
986 | collector.into_body_syntax_mapping(params, body) | ||
987 | } | 1011 | } |
988 | 1012 | ||
989 | pub(crate) fn body_syntax_mapping(db: &impl HirDatabase, func: Function) -> Arc<BodySyntaxMapping> { | 1013 | #[cfg(test)] |
990 | let (_, fn_def) = func.source(db); | 1014 | pub(crate) fn collect_fn_body_syntax(function: Function, node: &ast::FnDef) -> BodySyntaxMapping { |
991 | let body_syntax_mapping = collect_fn_body_syntax(&fn_def); | 1015 | let mut collector = ExprCollector::new(function); |
992 | Arc::new(body_syntax_mapping) | 1016 | collector.collect_fn_body(node); |
1017 | collector.into_body_syntax_mapping() | ||
993 | } | 1018 | } |