diff options
-rw-r--r-- | crates/ra_hir_def/src/body.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir_def/src/item_scope.rs | 105 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres.rs | 108 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir_def/src/resolver.rs | 3 |
5 files changed, 114 insertions, 108 deletions
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 401fe0b9b..d9ce6bcff 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs | |||
@@ -17,7 +17,8 @@ use rustc_hash::FxHashMap; | |||
17 | use crate::{ | 17 | use crate::{ |
18 | db::DefDatabase, | 18 | db::DefDatabase, |
19 | expr::{Expr, ExprId, Pat, PatId}, | 19 | expr::{Expr, ExprId, Pat, PatId}, |
20 | nameres::{BuiltinShadowMode, CrateDefMap}, | 20 | item_scope::BuiltinShadowMode, |
21 | nameres::CrateDefMap, | ||
21 | path::{ModPath, Path}, | 22 | path::{ModPath, Path}, |
22 | src::HasSource, | 23 | src::HasSource, |
23 | DefWithBodyId, HasModule, Lookup, ModuleDefId, ModuleId, | 24 | DefWithBodyId, HasModule, Lookup, ModuleDefId, ModuleId, |
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 8b1378917..62e7a02cb 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs | |||
@@ -1 +1,106 @@ | |||
1 | use hir_expand::name::Name; | ||
2 | use once_cell::sync::Lazy; | ||
3 | use rustc_hash::FxHashMap; | ||
1 | 4 | ||
5 | use crate::{per_ns::PerNs, BuiltinType, LocalImportId, MacroDefId, ModuleDefId, TraitId}; | ||
6 | |||
7 | #[derive(Debug, Default, PartialEq, Eq)] | ||
8 | pub struct ModuleScope { | ||
9 | pub(crate) items: FxHashMap<Name, Resolution>, | ||
10 | /// Macros visable in current module in legacy textual scope | ||
11 | /// | ||
12 | /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first. | ||
13 | /// If it yields no result, then it turns to module scoped `macros`. | ||
14 | /// It macros with name quatified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped, | ||
15 | /// and only normal scoped `macros` will be searched in. | ||
16 | /// | ||
17 | /// Note that this automatically inherit macros defined textually before the definition of module itself. | ||
18 | /// | ||
19 | /// Module scoped macros will be inserted into `items` instead of here. | ||
20 | // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will | ||
21 | // be all resolved to the last one defined if shadowing happens. | ||
22 | pub(crate) legacy_macros: FxHashMap<Name, MacroDefId>, | ||
23 | } | ||
24 | |||
25 | static BUILTIN_SCOPE: Lazy<FxHashMap<Name, Resolution>> = Lazy::new(|| { | ||
26 | BuiltinType::ALL | ||
27 | .iter() | ||
28 | .map(|(name, ty)| { | ||
29 | (name.clone(), Resolution { def: PerNs::types(ty.clone().into()), import: None }) | ||
30 | }) | ||
31 | .collect() | ||
32 | }); | ||
33 | |||
34 | /// Shadow mode for builtin type which can be shadowed by module. | ||
35 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | ||
36 | pub enum BuiltinShadowMode { | ||
37 | // Prefer Module | ||
38 | Module, | ||
39 | // Prefer Other Types | ||
40 | Other, | ||
41 | } | ||
42 | |||
43 | /// Legacy macros can only be accessed through special methods like `get_legacy_macros`. | ||
44 | /// Other methods will only resolve values, types and module scoped macros only. | ||
45 | impl ModuleScope { | ||
46 | pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, &'a Resolution)> + 'a { | ||
47 | //FIXME: shadowing | ||
48 | self.items.iter().chain(BUILTIN_SCOPE.iter()) | ||
49 | } | ||
50 | |||
51 | pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ { | ||
52 | self.entries() | ||
53 | .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None }) | ||
54 | .flat_map(|per_ns| { | ||
55 | per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter()) | ||
56 | }) | ||
57 | } | ||
58 | |||
59 | /// Iterate over all module scoped macros | ||
60 | pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { | ||
61 | self.items | ||
62 | .iter() | ||
63 | .filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_))) | ||
64 | } | ||
65 | |||
66 | /// Iterate over all legacy textual scoped macros visable at the end of the module | ||
67 | pub fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { | ||
68 | self.legacy_macros.iter().map(|(name, def)| (name, *def)) | ||
69 | } | ||
70 | |||
71 | /// Get a name from current module scope, legacy macros are not included | ||
72 | pub fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> { | ||
73 | match shadow { | ||
74 | BuiltinShadowMode::Module => self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)), | ||
75 | BuiltinShadowMode::Other => { | ||
76 | let item = self.items.get(name); | ||
77 | if let Some(res) = item { | ||
78 | if let Some(ModuleDefId::ModuleId(_)) = res.def.take_types() { | ||
79 | return BUILTIN_SCOPE.get(name).or(item); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | item.or_else(|| BUILTIN_SCOPE.get(name)) | ||
84 | } | ||
85 | } | ||
86 | } | ||
87 | |||
88 | pub fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a { | ||
89 | self.items.values().filter_map(|r| match r.def.take_types() { | ||
90 | Some(ModuleDefId::TraitId(t)) => Some(t), | ||
91 | _ => None, | ||
92 | }) | ||
93 | } | ||
94 | |||
95 | pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option<MacroDefId> { | ||
96 | self.legacy_macros.get(name).copied() | ||
97 | } | ||
98 | } | ||
99 | |||
100 | #[derive(Debug, Clone, PartialEq, Eq, Default)] | ||
101 | pub struct Resolution { | ||
102 | /// None for unresolved | ||
103 | pub def: PerNs, | ||
104 | /// ident by which this is imported into local scope. | ||
105 | pub import: Option<LocalImportId>, | ||
106 | } | ||
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index af52fa36e..0b486ce16 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs | |||
@@ -57,8 +57,7 @@ mod tests; | |||
57 | 57 | ||
58 | use std::sync::Arc; | 58 | use std::sync::Arc; |
59 | 59 | ||
60 | use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile, MacroDefId}; | 60 | use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile}; |
61 | use once_cell::sync::Lazy; | ||
62 | use ra_arena::Arena; | 61 | use ra_arena::Arena; |
63 | use ra_db::{CrateId, Edition, FileId, FilePosition}; | 62 | use ra_db::{CrateId, Edition, FileId, FilePosition}; |
64 | use ra_prof::profile; | 63 | use ra_prof::profile; |
@@ -69,12 +68,12 @@ use ra_syntax::{ | |||
69 | use rustc_hash::FxHashMap; | 68 | use rustc_hash::FxHashMap; |
70 | 69 | ||
71 | use crate::{ | 70 | use crate::{ |
72 | builtin_type::BuiltinType, | ||
73 | db::DefDatabase, | 71 | db::DefDatabase, |
72 | item_scope::{BuiltinShadowMode, ModuleScope}, | ||
74 | nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, | 73 | nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, |
75 | path::ModPath, | 74 | path::ModPath, |
76 | per_ns::PerNs, | 75 | per_ns::PerNs, |
77 | AstId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId, | 76 | AstId, ImplId, LocalModuleId, ModuleDefId, ModuleId, |
78 | }; | 77 | }; |
79 | 78 | ||
80 | /// Contains all top-level defs from a macro-expanded crate | 79 | /// Contains all top-level defs from a macro-expanded crate |
@@ -174,107 +173,6 @@ pub struct ModuleData { | |||
174 | pub impls: Vec<ImplId>, | 173 | pub impls: Vec<ImplId>, |
175 | } | 174 | } |
176 | 175 | ||
177 | #[derive(Debug, Default, PartialEq, Eq)] | ||
178 | pub struct ModuleScope { | ||
179 | items: FxHashMap<Name, Resolution>, | ||
180 | /// Macros visable in current module in legacy textual scope | ||
181 | /// | ||
182 | /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first. | ||
183 | /// If it yields no result, then it turns to module scoped `macros`. | ||
184 | /// It macros with name quatified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped, | ||
185 | /// and only normal scoped `macros` will be searched in. | ||
186 | /// | ||
187 | /// Note that this automatically inherit macros defined textually before the definition of module itself. | ||
188 | /// | ||
189 | /// Module scoped macros will be inserted into `items` instead of here. | ||
190 | // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will | ||
191 | // be all resolved to the last one defined if shadowing happens. | ||
192 | legacy_macros: FxHashMap<Name, MacroDefId>, | ||
193 | } | ||
194 | |||
195 | static BUILTIN_SCOPE: Lazy<FxHashMap<Name, Resolution>> = Lazy::new(|| { | ||
196 | BuiltinType::ALL | ||
197 | .iter() | ||
198 | .map(|(name, ty)| { | ||
199 | (name.clone(), Resolution { def: PerNs::types(ty.clone().into()), import: None }) | ||
200 | }) | ||
201 | .collect() | ||
202 | }); | ||
203 | |||
204 | /// Shadow mode for builtin type which can be shadowed by module. | ||
205 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | ||
206 | pub enum BuiltinShadowMode { | ||
207 | // Prefer Module | ||
208 | Module, | ||
209 | // Prefer Other Types | ||
210 | Other, | ||
211 | } | ||
212 | |||
213 | /// Legacy macros can only be accessed through special methods like `get_legacy_macros`. | ||
214 | /// Other methods will only resolve values, types and module scoped macros only. | ||
215 | impl ModuleScope { | ||
216 | pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, &'a Resolution)> + 'a { | ||
217 | //FIXME: shadowing | ||
218 | self.items.iter().chain(BUILTIN_SCOPE.iter()) | ||
219 | } | ||
220 | |||
221 | pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ { | ||
222 | self.entries() | ||
223 | .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None }) | ||
224 | .flat_map(|per_ns| { | ||
225 | per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter()) | ||
226 | }) | ||
227 | } | ||
228 | |||
229 | /// Iterate over all module scoped macros | ||
230 | pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { | ||
231 | self.items | ||
232 | .iter() | ||
233 | .filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_))) | ||
234 | } | ||
235 | |||
236 | /// Iterate over all legacy textual scoped macros visable at the end of the module | ||
237 | pub fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { | ||
238 | self.legacy_macros.iter().map(|(name, def)| (name, *def)) | ||
239 | } | ||
240 | |||
241 | /// Get a name from current module scope, legacy macros are not included | ||
242 | pub fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> { | ||
243 | match shadow { | ||
244 | BuiltinShadowMode::Module => self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)), | ||
245 | BuiltinShadowMode::Other => { | ||
246 | let item = self.items.get(name); | ||
247 | if let Some(res) = item { | ||
248 | if let Some(ModuleDefId::ModuleId(_)) = res.def.take_types() { | ||
249 | return BUILTIN_SCOPE.get(name).or(item); | ||
250 | } | ||
251 | } | ||
252 | |||
253 | item.or_else(|| BUILTIN_SCOPE.get(name)) | ||
254 | } | ||
255 | } | ||
256 | } | ||
257 | |||
258 | pub fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a { | ||
259 | self.items.values().filter_map(|r| match r.def.take_types() { | ||
260 | Some(ModuleDefId::TraitId(t)) => Some(t), | ||
261 | _ => None, | ||
262 | }) | ||
263 | } | ||
264 | |||
265 | fn get_legacy_macro(&self, name: &Name) -> Option<MacroDefId> { | ||
266 | self.legacy_macros.get(name).copied() | ||
267 | } | ||
268 | } | ||
269 | |||
270 | #[derive(Debug, Clone, PartialEq, Eq, Default)] | ||
271 | pub struct Resolution { | ||
272 | /// None for unresolved | ||
273 | pub def: PerNs, | ||
274 | /// ident by which this is imported into local scope. | ||
275 | pub import: Option<LocalImportId>, | ||
276 | } | ||
277 | |||
278 | impl CrateDefMap { | 176 | impl CrateDefMap { |
279 | pub(crate) fn crate_def_map_query( | 177 | pub(crate) fn crate_def_map_query( |
280 | // Note that this doesn't have `+ AstDatabase`! | 178 | // Note that this doesn't have `+ AstDatabase`! |
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index e68bf4868..ea6ce5f97 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -18,9 +18,10 @@ use test_utils::tested_by; | |||
18 | use crate::{ | 18 | use crate::{ |
19 | attr::Attrs, | 19 | attr::Attrs, |
20 | db::DefDatabase, | 20 | db::DefDatabase, |
21 | item_scope::Resolution, | ||
21 | nameres::{ | 22 | nameres::{ |
22 | diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, | 23 | diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, |
23 | raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, Resolution, ResolveMode, | 24 | raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode, |
24 | }, | 25 | }, |
25 | path::{ModPath, PathKind}, | 26 | path::{ModPath, PathKind}, |
26 | per_ns::PerNs, | 27 | per_ns::PerNs, |
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index af9d194f8..83013fed3 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs | |||
@@ -14,7 +14,8 @@ use crate::{ | |||
14 | db::DefDatabase, | 14 | db::DefDatabase, |
15 | expr::{ExprId, PatId}, | 15 | expr::{ExprId, PatId}, |
16 | generics::GenericParams, | 16 | generics::GenericParams, |
17 | nameres::{BuiltinShadowMode, CrateDefMap}, | 17 | item_scope::BuiltinShadowMode, |
18 | nameres::CrateDefMap, | ||
18 | path::{ModPath, PathKind}, | 19 | path::{ModPath, PathKind}, |
19 | per_ns::PerNs, | 20 | per_ns::PerNs, |
20 | AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, | 21 | AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, |