aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-01-23 22:08:41 +0000
committerFlorian Diebold <[email protected]>2019-02-01 21:17:48 +0000
commit758bc72873efe36f579236d1abf240d14866fd82 (patch)
treea8c416c5c2c3dfb834bf29ed2ca4fae666048a59
parent5208c2aa930ae452e062dcdc2563c1bbb67d2e4a (diff)
Implement methods to build a resolver
-rw-r--r--crates/ra_hir/src/code_model_api.rs22
-rw-r--r--crates/ra_hir/src/expr.rs129
-rw-r--r--crates/ra_hir/src/expr/scope.rs11
-rw-r--r--crates/ra_hir/src/impl_block.rs45
-rw-r--r--crates/ra_hir/src/resolve.rs32
5 files changed, 166 insertions, 73 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 73541a8c3..b8ca04c5c 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -184,9 +184,9 @@ impl Module {
184 self.problems_impl(db) 184 self.problems_impl(db)
185 } 185 }
186 186
187 #[allow(unused_variables)]
188 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { 187 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver {
189 unimplemented!() 188 let item_map = db.item_map(self.krate);
189 Resolver::default().push_module_scope(item_map, self.module_id)
190 } 190 }
191} 191}
192 192
@@ -480,6 +480,24 @@ impl Function {
480 pub fn generic_params(&self, db: &impl PersistentHirDatabase) -> Arc<GenericParams> { 480 pub fn generic_params(&self, db: &impl PersistentHirDatabase) -> Arc<GenericParams> {
481 db.generic_params((*self).into()) 481 db.generic_params((*self).into())
482 } 482 }
483
484 // TODO move to a more general type for 'body-having' items
485 /// Builds a resolver for code inside this item.
486 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver {
487 // take the outer scope...
488 let r = self
489 .impl_block(db)
490 .map(|ib| ib.resolver(db))
491 .unwrap_or_else(|| self.module(db).resolver(db));
492 // ...and add generic params, if present
493 let p = self.generic_params(db);
494 let r = if !p.params.is_empty() {
495 r.push_generic_params_scope(p)
496 } else {
497 r
498 };
499 r
500 }
483} 501}
484 502
485impl Docs for Function { 503impl Docs for Function {
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)]
29pub struct Body { 29pub 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)]
76pub 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
72impl Index<ExprId> for Body { 89impl 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
455struct ExprCollector { 472struct 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
464impl ExprCollector { 484impl 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
948pub(crate) fn collect_fn_body_syntax(node: &ast::FnDef) -> BodySyntaxMapping { 1004pub(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
989pub(crate) fn body_syntax_mapping(db: &impl HirDatabase, func: Function) -> Arc<BodySyntaxMapping> { 1013#[cfg(test)]
990 let (_, fn_def) = func.source(db); 1014pub(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}
diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs
index 504a087a3..887ad8dd8 100644
--- a/crates/ra_hir/src/expr/scope.rs
+++ b/crates/ra_hir/src/expr/scope.rs
@@ -338,6 +338,7 @@ pub struct ReferenceDescriptor {
338mod tests { 338mod tests {
339 use ra_syntax::{SourceFile, algo::find_node_at_offset}; 339 use ra_syntax::{SourceFile, algo::find_node_at_offset};
340 use test_utils::{extract_offset, assert_eq_text}; 340 use test_utils::{extract_offset, assert_eq_text};
341 use ra_arena::ArenaId;
341 342
342 use crate::expr; 343 use crate::expr;
343 344
@@ -356,7 +357,10 @@ mod tests {
356 let file = SourceFile::parse(&code); 357 let file = SourceFile::parse(&code);
357 let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); 358 let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap();
358 let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); 359 let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap();
359 let body_hir = expr::collect_fn_body_syntax(fn_def); 360 let irrelevant_function = Function {
361 id: crate::ids::FunctionId::from_raw(0.into()),
362 };
363 let body_hir = expr::collect_fn_body_syntax(irrelevant_function, fn_def);
360 let scopes = ExprScopes::new(Arc::clone(body_hir.body())); 364 let scopes = ExprScopes::new(Arc::clone(body_hir.body()));
361 let scopes = ScopesWithSyntaxMapping { 365 let scopes = ScopesWithSyntaxMapping {
362 scopes: Arc::new(scopes), 366 scopes: Arc::new(scopes),
@@ -456,7 +460,10 @@ mod tests {
456 let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); 460 let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap();
457 let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); 461 let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap();
458 462
459 let body_hir = expr::collect_fn_body_syntax(fn_def); 463 let irrelevant_function = Function {
464 id: crate::ids::FunctionId::from_raw(0.into()),
465 };
466 let body_hir = expr::collect_fn_body_syntax(irrelevant_function, fn_def);
460 let scopes = ExprScopes::new(Arc::clone(body_hir.body())); 467 let scopes = ExprScopes::new(Arc::clone(body_hir.body()));
461 let scopes = ScopesWithSyntaxMapping { 468 let scopes = ScopesWithSyntaxMapping {
462 scopes: Arc::new(scopes), 469 scopes: Arc::new(scopes),
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index 36d72b103..5fa49d456 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -9,9 +9,11 @@ ast::{self, AstNode}};
9use crate::{ 9use crate::{
10 Const, Type, 10 Const, Type,
11 Function, HirFileId, 11 Function, HirFileId,
12 HirDatabase,
12 PersistentHirDatabase, 13 PersistentHirDatabase,
13 type_ref::TypeRef, 14 type_ref::TypeRef,
14 ids::LocationCtx, 15 ids::LocationCtx,
16 resolve::Resolver,
15}; 17};
16 18
17use crate::code_model_api::{Module, ModuleSource}; 19use crate::code_model_api::{Module, ModuleSource};
@@ -69,6 +71,10 @@ impl ImplBlock {
69 &self.module_impl_blocks.impls[self.impl_id] 71 &self.module_impl_blocks.impls[self.impl_id]
70 } 72 }
71 73
74 pub fn module(&self) -> Module {
75 self.module_impl_blocks.module.clone()
76 }
77
72 pub fn target_trait(&self) -> Option<&TypeRef> { 78 pub fn target_trait(&self) -> Option<&TypeRef> {
73 self.impl_data().target_trait() 79 self.impl_data().target_trait()
74 } 80 }
@@ -80,6 +86,13 @@ impl ImplBlock {
80 pub fn items(&self) -> &[ImplItem] { 86 pub fn items(&self) -> &[ImplItem] {
81 self.impl_data().items() 87 self.impl_data().items()
82 } 88 }
89
90 pub fn resolver(&self, db: &impl HirDatabase) -> Resolver {
91 let r = self.module().resolver(db);
92 // FIXME: add generics
93 let r = r.push_impl_block_scope(self.clone());
94 r
95 }
83} 96}
84 97
85#[derive(Debug, Clone, PartialEq, Eq)] 98#[derive(Debug, Clone, PartialEq, Eq)]
@@ -162,25 +175,24 @@ impl_arena_id!(ImplId);
162/// we don't need to do the second step again. 175/// we don't need to do the second step again.
163#[derive(Debug, PartialEq, Eq)] 176#[derive(Debug, PartialEq, Eq)]
164pub struct ModuleImplBlocks { 177pub struct ModuleImplBlocks {
178 module: Module,
165 pub(crate) impls: Arena<ImplId, ImplData>, 179 pub(crate) impls: Arena<ImplId, ImplData>,
166 impls_by_def: FxHashMap<ImplItem, ImplId>, 180 impls_by_def: FxHashMap<ImplItem, ImplId>,
167} 181}
168 182
169impl ModuleImplBlocks { 183impl ModuleImplBlocks {
170 fn new() -> Self {
171 ModuleImplBlocks {
172 impls: Arena::default(),
173 impls_by_def: FxHashMap::default(),
174 }
175 }
176
177 fn collect( 184 fn collect(
178 &mut self,
179 db: &impl PersistentHirDatabase, 185 db: &impl PersistentHirDatabase,
180 module: Module, 186 module: Module,
181 source_map: &mut ImplSourceMap, 187 source_map: &mut ImplSourceMap,
182 ) { 188 ) -> Self {
183 let (file_id, module_source) = module.definition_source(db); 189 let mut m = ModuleImplBlocks {
190 module,
191 impls: Arena::default(),
192 impls_by_def: FxHashMap::default(),
193 };
194
195 let (file_id, module_source) = m.module.definition_source(db);
184 let file_id: HirFileId = file_id.into(); 196 let file_id: HirFileId = file_id.into();
185 let node = match &module_source { 197 let node = match &module_source {
186 ModuleSource::SourceFile(node) => node.syntax(), 198 ModuleSource::SourceFile(node) => node.syntax(),
@@ -191,14 +203,16 @@ impl ModuleImplBlocks {
191 }; 203 };
192 204
193 for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) { 205 for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) {
194 let impl_block = ImplData::from_ast(db, file_id, module, impl_block_ast); 206 let impl_block = ImplData::from_ast(db, file_id, m.module, impl_block_ast);
195 let id = self.impls.alloc(impl_block); 207 let id = m.impls.alloc(impl_block);
196 for &impl_item in &self.impls[id].items { 208 for &impl_item in &m.impls[id].items {
197 self.impls_by_def.insert(impl_item, id); 209 m.impls_by_def.insert(impl_item, id);
198 } 210 }
199 211
200 source_map.insert(id, impl_block_ast); 212 source_map.insert(id, impl_block_ast);
201 } 213 }
214
215 m
202 } 216 }
203} 217}
204 218
@@ -208,8 +222,7 @@ pub(crate) fn impls_in_module_with_source_map_query(
208) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>) { 222) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>) {
209 let mut source_map = ImplSourceMap::default(); 223 let mut source_map = ImplSourceMap::default();
210 224
211 let mut result = ModuleImplBlocks::new(); 225 let result = ModuleImplBlocks::collect(db, module, &mut source_map);
212 result.collect(db, module, &mut source_map);
213 226
214 (Arc::new(result), Arc::new(source_map)) 227 (Arc::new(result), Arc::new(source_map))
215} 228}
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index 41fcb35bc..b7fbf6df2 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -15,7 +15,7 @@ use crate::{
15 path::Path, 15 path::Path,
16}; 16};
17 17
18#[derive(Debug, Clone)] 18#[derive(Debug, Clone, Default)]
19pub struct Resolver { 19pub struct Resolver {
20 scopes: Vec<Scope>, // maybe a 'linked list' of scopes? or allow linking a Resolver to a parent Resolver? that's an optimization that might not be necessary, though 20 scopes: Vec<Scope>, // maybe a 'linked list' of scopes? or allow linking a Resolver to a parent Resolver? that's an optimization that might not be necessary, though
21} 21}
@@ -87,6 +87,36 @@ impl Resolver {
87 self 87 self
88 } 88 }
89 89
90 pub(crate) fn push_generic_params_scope(self, params: Arc<GenericParams>) -> Resolver {
91 self.push_scope(Scope::GenericParams(params))
92 }
93
94 pub(crate) fn push_impl_block_scope(self, impl_block: ImplBlock) -> Resolver {
95 self.push_scope(Scope::ImplBlockScope(impl_block))
96 }
97
98 pub(crate) fn push_module_scope(self, item_map: Arc<ItemMap>, module_id: ModuleId) -> Resolver {
99 self.push_scope(Scope::ModuleScope(ModuleItemMap {
100 item_map,
101 module_id,
102 }))
103 }
104
105 pub(crate) fn push_expr_scope(
106 self,
107 expr_scopes: Arc<ExprScopes>,
108 scope_id: ScopeId,
109 ) -> Resolver {
110 self.push_scope(Scope::ExprScope(ExprScope {
111 expr_scopes,
112 scope_id,
113 }))
114 }
115
116 pub(crate) fn push_function_params(self, body: Arc<Body>) -> Resolver {
117 self.push_scope(Scope::FunctionParams(body))
118 }
119
90 pub(crate) fn pop_scope(mut self) -> Resolver { 120 pub(crate) fn pop_scope(mut self) -> Resolver {
91 self.scopes.pop(); 121 self.scopes.pop();
92 self 122 self