aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r--crates/ra_hir_def/src/body.rs3
-rw-r--r--crates/ra_hir_def/src/item_scope.rs105
-rw-r--r--crates/ra_hir_def/src/nameres.rs108
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs3
-rw-r--r--crates/ra_hir_def/src/resolver.rs3
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;
17use crate::{ 17use 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 @@
1use hir_expand::name::Name;
2use once_cell::sync::Lazy;
3use rustc_hash::FxHashMap;
1 4
5use crate::{per_ns::PerNs, BuiltinType, LocalImportId, MacroDefId, ModuleDefId, TraitId};
6
7#[derive(Debug, Default, PartialEq, Eq)]
8pub 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
25static 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)]
36pub 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.
45impl 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)]
101pub 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
58use std::sync::Arc; 58use std::sync::Arc;
59 59
60use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile, MacroDefId}; 60use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile};
61use once_cell::sync::Lazy;
62use ra_arena::Arena; 61use ra_arena::Arena;
63use ra_db::{CrateId, Edition, FileId, FilePosition}; 62use ra_db::{CrateId, Edition, FileId, FilePosition};
64use ra_prof::profile; 63use ra_prof::profile;
@@ -69,12 +68,12 @@ use ra_syntax::{
69use rustc_hash::FxHashMap; 68use rustc_hash::FxHashMap;
70 69
71use crate::{ 70use 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)]
178pub 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
195static 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)]
206pub 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.
215impl 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)]
271pub 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
278impl CrateDefMap { 176impl 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;
18use crate::{ 18use 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,