aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/resolve.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/resolve.rs')
-rw-r--r--crates/ra_hir/src/resolve.rs116
1 files changed, 82 insertions, 34 deletions
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index b7fbf6df2..36daed65b 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -1,30 +1,29 @@
1#![allow(unused_variables, dead_code)]
2//! Name resolution. 1//! Name resolution.
3use std::sync::Arc; 2use std::sync::Arc;
4 3
5use rustc_hash::FxHashMap; 4use rustc_hash::FxHashMap;
6 5
7use crate::{ 6use crate::{
8 ModuleDef, 7 ModuleDef, Module,
9 name::Name, 8 db::HirDatabase,
10 nameres::{PerNs, lower::ImportId, ItemMap}, 9 name::{Name, KnownName},
11 module_tree::ModuleId, 10 nameres::{PerNs, ItemMap},
12 generics::GenericParams, 11 generics::GenericParams,
13 expr::{Body, scope::{ExprScopes, ScopeId}, PatId}, 12 expr::{scope::{ExprScopes, ScopeId}, PatId},
14 impl_block::ImplBlock, 13 impl_block::ImplBlock,
15 path::Path, 14 path::Path,
16}; 15};
17 16
18#[derive(Debug, Clone, Default)] 17#[derive(Debug, Clone, Default)]
19pub struct Resolver { 18pub 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 19 scopes: Vec<Scope>,
21} 20}
22 21
23// TODO how to store these best 22// TODO how to store these best
24#[derive(Debug, Clone)] 23#[derive(Debug, Clone)]
25pub(crate) struct ModuleItemMap { 24pub(crate) struct ModuleItemMap {
26 item_map: Arc<ItemMap>, 25 item_map: Arc<ItemMap>,
27 module_id: ModuleId, 26 module: Module,
28} 27}
29 28
30#[derive(Debug, Clone)] 29#[derive(Debug, Clone)]
@@ -39,8 +38,6 @@ pub(crate) enum Scope {
39 ModuleScope(ModuleItemMap), 38 ModuleScope(ModuleItemMap),
40 /// Brings the generic parameters of an item into scope 39 /// Brings the generic parameters of an item into scope
41 GenericParams(Arc<GenericParams>), 40 GenericParams(Arc<GenericParams>),
42 /// Brings the function parameters into scope
43 FunctionParams(Arc<Body>),
44 /// Brings `Self` into scope 41 /// Brings `Self` into scope
45 ImplBlockScope(ImplBlock), 42 ImplBlockScope(ImplBlock),
46 /// Local bindings 43 /// Local bindings
@@ -49,36 +46,64 @@ pub(crate) enum Scope {
49 46
50#[derive(Debug, Clone, PartialEq, Eq)] 47#[derive(Debug, Clone, PartialEq, Eq)]
51pub enum Resolution { 48pub enum Resolution {
49 // FIXME make these tuple variants
52 /// An item 50 /// An item
53 Def { 51 Def {
54 def: ModuleDef, 52 def: ModuleDef,
55 import: Option<ImportId>,
56 }, 53 },
57 /// A local binding (only value namespace) 54 /// A local binding (only value namespace)
58 LocalBinding { pat: PatId }, 55 LocalBinding {
56 pat: PatId,
57 },
59 /// A generic parameter 58 /// A generic parameter
60 GenericParam { idx: u32 }, 59 GenericParam {
61 // TODO how does `Self` resolve? 60 idx: u32,
61 },
62 SelfType(ImplBlock),
62} 63}
63 64
64impl Resolver { 65impl Resolver {
65 pub fn resolve_name(&self, name: &Name) -> PerNs<Resolution> { 66 pub fn resolve_name(&self, name: &Name) -> PerNs<Resolution> {
67 let mut resolution = PerNs::none();
66 for scope in self.scopes.iter().rev() { 68 for scope in self.scopes.iter().rev() {
67 let resolution = scope.resolve_name(name); 69 resolution = resolution.combine(scope.resolve_name(name));
68 if !resolution.is_none() { 70 if resolution.is_both() {
69 return resolution; 71 return resolution;
70 } 72 }
71 } 73 }
72 PerNs::none() 74 resolution
73 } 75 }
74 76
75 pub fn resolve_path(&self, path: &Path) -> PerNs<Resolution> { 77 pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs<Resolution> {
76 unimplemented!() 78 if let Some(name) = path.as_ident() {
79 self.resolve_name(name)
80 } else if path.is_self() {
81 self.resolve_name(&Name::self_param())
82 } else {
83 let (item_map, module) = match self.module() {
84 Some(m) => m,
85 _ => return PerNs::none(),
86 };
87 let module_res = item_map.resolve_path(db, module, path);
88 module_res.map(|def| Resolution::Def { def })
89 }
77 } 90 }
78 91
79 pub fn all_names(&self) -> FxHashMap<Name, Resolution> { 92 pub fn all_names(&self) -> FxHashMap<Name, Resolution> {
80 unimplemented!() 93 unimplemented!()
81 } 94 }
95
96 fn module(&self) -> Option<(&ItemMap, Module)> {
97 for scope in self.scopes.iter().rev() {
98 match scope {
99 Scope::ModuleScope(m) => {
100 return Some((&m.item_map, m.module.clone()));
101 }
102 _ => {}
103 }
104 }
105 None
106 }
82} 107}
83 108
84impl Resolver { 109impl Resolver {
@@ -95,11 +120,8 @@ impl Resolver {
95 self.push_scope(Scope::ImplBlockScope(impl_block)) 120 self.push_scope(Scope::ImplBlockScope(impl_block))
96 } 121 }
97 122
98 pub(crate) fn push_module_scope(self, item_map: Arc<ItemMap>, module_id: ModuleId) -> Resolver { 123 pub(crate) fn push_module_scope(self, item_map: Arc<ItemMap>, module: Module) -> Resolver {
99 self.push_scope(Scope::ModuleScope(ModuleItemMap { 124 self.push_scope(Scope::ModuleScope(ModuleItemMap { item_map, module }))
100 item_map,
101 module_id,
102 }))
103 } 125 }
104 126
105 pub(crate) fn push_expr_scope( 127 pub(crate) fn push_expr_scope(
@@ -112,19 +134,45 @@ impl Resolver {
112 scope_id, 134 scope_id,
113 })) 135 }))
114 } 136 }
115
116 pub(crate) fn push_function_params(self, body: Arc<Body>) -> Resolver {
117 self.push_scope(Scope::FunctionParams(body))
118 }
119
120 pub(crate) fn pop_scope(mut self) -> Resolver {
121 self.scopes.pop();
122 self
123 }
124} 137}
125 138
126impl Scope { 139impl Scope {
127 fn resolve_name(&self, name: &Name) -> PerNs<Resolution> { 140 fn resolve_name(&self, name: &Name) -> PerNs<Resolution> {
128 unimplemented!() 141 match self {
142 Scope::ModuleScope(m) => {
143 if let Some(KnownName::SelfParam) = name.as_known_name() {
144 PerNs::types(Resolution::Def {
145 def: m.module.into(),
146 })
147 } else {
148 match m.item_map[m.module.module_id].get(name) {
149 Some(res) => res.def.map(|def| Resolution::Def { def }),
150 None => PerNs::none(),
151 }
152 }
153 }
154 Scope::GenericParams(gp) => match gp.find_by_name(name) {
155 Some(gp) => PerNs::types(Resolution::GenericParam { idx: gp.idx }),
156 None => PerNs::none(),
157 },
158 Scope::ImplBlockScope(i) => {
159 if name.as_known_name() == Some(KnownName::SelfType) {
160 PerNs::types(Resolution::SelfType(i.clone()))
161 } else {
162 PerNs::none()
163 }
164 }
165 Scope::ExprScope(e) => {
166 let entry = e
167 .expr_scopes
168 .entries(e.scope_id)
169 .iter()
170 .find(|entry| entry.name() == name);
171 match entry {
172 Some(e) => PerNs::values(Resolution::LocalBinding { pat: e.pat() }),
173 None => PerNs::none(),
174 }
175 }
176 }
129 } 177 }
130} 178}