diff options
Diffstat (limited to 'crates/ra_hir/src/expr.rs')
-rw-r--r-- | crates/ra_hir/src/expr.rs | 143 |
1 files changed, 91 insertions, 52 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index f4a950418..f9f702ae2 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -10,15 +10,15 @@ use ra_syntax::{ | |||
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | Path, Name, Function, | 13 | Path, Name, HirDatabase, Function, Resolver, |
14 | name::AsName, HirDatabase, | 14 | name::AsName, |
15 | type_ref::{Mutability, TypeRef}, | 15 | type_ref::{Mutability, TypeRef}, |
16 | }; | 16 | }; |
17 | use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}; | 17 | use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}; |
18 | 18 | ||
19 | pub use self::scope::{ExprScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax}; | 19 | pub use self::scope::{ExprScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax}; |
20 | 20 | ||
21 | mod scope; | 21 | pub(crate) mod scope; |
22 | 22 | ||
23 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | 23 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
24 | pub struct ExprId(RawId); | 24 | pub struct ExprId(RawId); |
@@ -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 |
@@ -62,6 +65,34 @@ impl Body { | |||
62 | pub fn body_expr(&self) -> ExprId { | 65 | pub fn body_expr(&self) -> ExprId { |
63 | self.body_expr | 66 | self.body_expr |
64 | } | 67 | } |
68 | |||
69 | pub fn owner(&self) -> Function { | ||
70 | self.owner | ||
71 | } | ||
72 | |||
73 | pub fn syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> { | ||
74 | db.body_syntax_mapping(self.owner) | ||
75 | } | ||
76 | } | ||
77 | |||
78 | // needs arbitrary_self_types to be a method... or maybe move to the def? | ||
79 | pub fn resolver_for_expr(body: Arc<Body>, db: &impl HirDatabase, expr_id: ExprId) -> Resolver { | ||
80 | let scopes = db.expr_scopes(body.owner); | ||
81 | resolver_for_scope(body, db, scopes.scope_for(expr_id)) | ||
82 | } | ||
83 | |||
84 | pub fn resolver_for_scope( | ||
85 | body: Arc<Body>, | ||
86 | db: &impl HirDatabase, | ||
87 | scope_id: Option<scope::ScopeId>, | ||
88 | ) -> Resolver { | ||
89 | let mut r = body.owner.resolver(db); | ||
90 | let scopes = db.expr_scopes(body.owner); | ||
91 | let scope_chain = scopes.scope_chain_for(scope_id).collect::<Vec<_>>(); | ||
92 | for scope in scope_chain.into_iter().rev() { | ||
93 | r = r.push_expr_scope(Arc::clone(&scopes), scope); | ||
94 | } | ||
95 | r | ||
65 | } | 96 | } |
66 | 97 | ||
67 | impl Index<ExprId> for Body { | 98 | impl Index<ExprId> for Body { |
@@ -448,23 +479,29 @@ pub(crate) fn body_hir(db: &impl HirDatabase, func: Function) -> Arc<Body> { | |||
448 | } | 479 | } |
449 | 480 | ||
450 | struct ExprCollector { | 481 | struct ExprCollector { |
482 | owner: Function, | ||
451 | exprs: Arena<ExprId, Expr>, | 483 | exprs: Arena<ExprId, Expr>, |
452 | pats: Arena<PatId, Pat>, | 484 | pats: Arena<PatId, Pat>, |
453 | expr_syntax_mapping: FxHashMap<SyntaxNodePtr, ExprId>, | 485 | expr_syntax_mapping: FxHashMap<SyntaxNodePtr, ExprId>, |
454 | expr_syntax_mapping_back: ArenaMap<ExprId, SyntaxNodePtr>, | 486 | expr_syntax_mapping_back: ArenaMap<ExprId, SyntaxNodePtr>, |
455 | pat_syntax_mapping: FxHashMap<SyntaxNodePtr, PatId>, | 487 | pat_syntax_mapping: FxHashMap<SyntaxNodePtr, PatId>, |
456 | pat_syntax_mapping_back: ArenaMap<PatId, SyntaxNodePtr>, | 488 | pat_syntax_mapping_back: ArenaMap<PatId, SyntaxNodePtr>, |
489 | params: Vec<PatId>, | ||
490 | body_expr: Option<ExprId>, | ||
457 | } | 491 | } |
458 | 492 | ||
459 | impl ExprCollector { | 493 | impl ExprCollector { |
460 | fn new() -> Self { | 494 | fn new(owner: Function) -> Self { |
461 | ExprCollector { | 495 | ExprCollector { |
496 | owner, | ||
462 | exprs: Arena::default(), | 497 | exprs: Arena::default(), |
463 | pats: Arena::default(), | 498 | pats: Arena::default(), |
464 | expr_syntax_mapping: FxHashMap::default(), | 499 | expr_syntax_mapping: FxHashMap::default(), |
465 | expr_syntax_mapping_back: ArenaMap::default(), | 500 | expr_syntax_mapping_back: ArenaMap::default(), |
466 | pat_syntax_mapping: FxHashMap::default(), | 501 | pat_syntax_mapping: FxHashMap::default(), |
467 | pat_syntax_mapping_back: ArenaMap::default(), | 502 | pat_syntax_mapping_back: ArenaMap::default(), |
503 | params: Vec::new(), | ||
504 | body_expr: None, | ||
468 | } | 505 | } |
469 | } | 506 | } |
470 | 507 | ||
@@ -902,10 +939,7 @@ impl ExprCollector { | |||
902 | }); | 939 | }); |
903 | fields.extend(iter); | 940 | fields.extend(iter); |
904 | 941 | ||
905 | Pat::Struct { | 942 | Pat::Struct { path, args: fields } |
906 | path: path, | ||
907 | args: fields, | ||
908 | } | ||
909 | } | 943 | } |
910 | 944 | ||
911 | // TODO: implement | 945 | // TODO: implement |
@@ -923,12 +957,48 @@ impl ExprCollector { | |||
923 | } | 957 | } |
924 | } | 958 | } |
925 | 959 | ||
926 | fn into_body_syntax_mapping(self, params: Vec<PatId>, body_expr: ExprId) -> BodySyntaxMapping { | 960 | fn collect_fn_body(&mut self, node: &ast::FnDef) { |
961 | if let Some(param_list) = node.param_list() { | ||
962 | if let Some(self_param) = param_list.self_param() { | ||
963 | let self_param = SyntaxNodePtr::new( | ||
964 | self_param | ||
965 | .self_kw() | ||
966 | .expect("self param without self keyword") | ||
967 | .syntax(), | ||
968 | ); | ||
969 | let param_pat = self.alloc_pat( | ||
970 | Pat::Bind { | ||
971 | name: Name::self_param(), | ||
972 | mode: BindingAnnotation::Unannotated, | ||
973 | subpat: None, | ||
974 | }, | ||
975 | self_param, | ||
976 | ); | ||
977 | self.params.push(param_pat); | ||
978 | } | ||
979 | |||
980 | for param in param_list.params() { | ||
981 | let pat = if let Some(pat) = param.pat() { | ||
982 | pat | ||
983 | } else { | ||
984 | continue; | ||
985 | }; | ||
986 | let param_pat = self.collect_pat(pat); | ||
987 | self.params.push(param_pat); | ||
988 | } | ||
989 | }; | ||
990 | |||
991 | let body = self.collect_block_opt(node.body()); | ||
992 | self.body_expr = Some(body); | ||
993 | } | ||
994 | |||
995 | fn into_body_syntax_mapping(self) -> BodySyntaxMapping { | ||
927 | let body = Body { | 996 | let body = Body { |
997 | owner: self.owner, | ||
928 | exprs: self.exprs, | 998 | exprs: self.exprs, |
929 | pats: self.pats, | 999 | pats: self.pats, |
930 | params, | 1000 | params: self.params, |
931 | body_expr, | 1001 | body_expr: self.body_expr.expect("A body should have been collected"), |
932 | }; | 1002 | }; |
933 | BodySyntaxMapping { | 1003 | BodySyntaxMapping { |
934 | body: Arc::new(body), | 1004 | body: Arc::new(body), |
@@ -940,49 +1010,18 @@ impl ExprCollector { | |||
940 | } | 1010 | } |
941 | } | 1011 | } |
942 | 1012 | ||
943 | pub(crate) fn collect_fn_body_syntax(node: &ast::FnDef) -> BodySyntaxMapping { | 1013 | pub(crate) fn body_syntax_mapping(db: &impl HirDatabase, func: Function) -> Arc<BodySyntaxMapping> { |
944 | let mut collector = ExprCollector::new(); | 1014 | let mut collector = ExprCollector::new(func); |
945 | |||
946 | let params = if let Some(param_list) = node.param_list() { | ||
947 | let mut params = Vec::new(); | ||
948 | |||
949 | if let Some(self_param) = param_list.self_param() { | ||
950 | let self_param = SyntaxNodePtr::new( | ||
951 | self_param | ||
952 | .self_kw() | ||
953 | .expect("self param without self keyword") | ||
954 | .syntax(), | ||
955 | ); | ||
956 | let param = collector.alloc_pat( | ||
957 | Pat::Bind { | ||
958 | name: Name::self_param(), | ||
959 | mode: BindingAnnotation::Unannotated, | ||
960 | subpat: None, | ||
961 | }, | ||
962 | self_param, | ||
963 | ); | ||
964 | params.push(param); | ||
965 | } | ||
966 | 1015 | ||
967 | for param in param_list.params() { | 1016 | // TODO: consts, etc. |
968 | let pat = if let Some(pat) = param.pat() { | 1017 | collector.collect_fn_body(&func.source(db).1); |
969 | pat | ||
970 | } else { | ||
971 | continue; | ||
972 | }; | ||
973 | params.push(collector.collect_pat(pat)); | ||
974 | } | ||
975 | params | ||
976 | } else { | ||
977 | Vec::new() | ||
978 | }; | ||
979 | 1018 | ||
980 | let body = collector.collect_block_opt(node.body()); | 1019 | Arc::new(collector.into_body_syntax_mapping()) |
981 | collector.into_body_syntax_mapping(params, body) | ||
982 | } | 1020 | } |
983 | 1021 | ||
984 | pub(crate) fn body_syntax_mapping(db: &impl HirDatabase, func: Function) -> Arc<BodySyntaxMapping> { | 1022 | #[cfg(test)] |
985 | let (_, fn_def) = func.source(db); | 1023 | pub(crate) fn collect_fn_body_syntax(function: Function, node: &ast::FnDef) -> BodySyntaxMapping { |
986 | let body_syntax_mapping = collect_fn_body_syntax(&fn_def); | 1024 | let mut collector = ExprCollector::new(function); |
987 | Arc::new(body_syntax_mapping) | 1025 | collector.collect_fn_body(node); |
1026 | collector.into_body_syntax_mapping() | ||
988 | } | 1027 | } |