diff options
Diffstat (limited to 'crates/ra_hir_def/src/nameres.rs')
-rw-r--r-- | crates/ra_hir_def/src/nameres.rs | 130 |
1 files changed, 62 insertions, 68 deletions
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index c01e020ef..2359386c2 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs | |||
@@ -47,8 +47,7 @@ | |||
47 | //! path and, upon success, we run macro expansion and "collect module" phase on | 47 | //! path and, upon success, we run macro expansion and "collect module" phase on |
48 | //! the result | 48 | //! the result |
49 | 49 | ||
50 | pub mod raw; | 50 | pub(crate) mod raw; |
51 | pub mod per_ns; | ||
52 | mod collector; | 51 | mod collector; |
53 | mod mod_resolution; | 52 | mod mod_resolution; |
54 | mod path_resolution; | 53 | mod path_resolution; |
@@ -58,70 +57,63 @@ mod tests; | |||
58 | 57 | ||
59 | use std::sync::Arc; | 58 | use std::sync::Arc; |
60 | 59 | ||
61 | use hir_expand::{ast_id_map::FileAstId, diagnostics::DiagnosticSink, name::Name, MacroDefId}; | 60 | use hir_expand::{ |
61 | ast_id_map::FileAstId, diagnostics::DiagnosticSink, either::Either, name::Name, MacroDefId, | ||
62 | Source, | ||
63 | }; | ||
62 | use once_cell::sync::Lazy; | 64 | use once_cell::sync::Lazy; |
63 | use ra_arena::Arena; | 65 | use ra_arena::Arena; |
64 | use ra_db::{CrateId, Edition, FileId}; | 66 | use ra_db::{CrateId, Edition, FileId}; |
65 | use ra_prof::profile; | 67 | use ra_prof::profile; |
66 | use ra_syntax::ast; | 68 | use ra_syntax::ast; |
67 | use rustc_hash::{FxHashMap, FxHashSet}; | 69 | use rustc_hash::FxHashMap; |
68 | 70 | ||
69 | use crate::{ | 71 | use crate::{ |
70 | builtin_type::BuiltinType, | 72 | builtin_type::BuiltinType, |
71 | db::DefDatabase2, | 73 | db::DefDatabase, |
72 | nameres::{ | 74 | nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, |
73 | diagnostics::DefDiagnostic, path_resolution::ResolveMode, per_ns::PerNs, raw::ImportId, | ||
74 | }, | ||
75 | path::Path, | 75 | path::Path, |
76 | AstId, CrateModuleId, FunctionId, ImplId, ModuleDefId, ModuleId, TraitId, | 76 | per_ns::PerNs, |
77 | AstId, FunctionId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId, | ||
77 | }; | 78 | }; |
78 | 79 | ||
79 | /// Contains all top-level defs from a macro-expanded crate | 80 | /// Contains all top-level defs from a macro-expanded crate |
80 | #[derive(Debug, PartialEq, Eq)] | 81 | #[derive(Debug, PartialEq, Eq)] |
81 | pub struct CrateDefMap { | 82 | pub struct CrateDefMap { |
82 | krate: CrateId, | 83 | pub root: LocalModuleId, |
83 | edition: Edition, | 84 | pub modules: Arena<LocalModuleId, ModuleData>, |
85 | pub(crate) krate: CrateId, | ||
84 | /// The prelude module for this crate. This either comes from an import | 86 | /// The prelude module for this crate. This either comes from an import |
85 | /// marked with the `prelude_import` attribute, or (in the normal case) from | 87 | /// marked with the `prelude_import` attribute, or (in the normal case) from |
86 | /// a dependency (`std` or `core`). | 88 | /// a dependency (`std` or `core`). |
87 | prelude: Option<ModuleId>, | 89 | pub(crate) prelude: Option<ModuleId>, |
88 | extern_prelude: FxHashMap<Name, ModuleDefId>, | 90 | pub(crate) extern_prelude: FxHashMap<Name, ModuleDefId>, |
89 | root: CrateModuleId, | ||
90 | modules: Arena<CrateModuleId, ModuleData>, | ||
91 | |||
92 | /// Some macros are not well-behavior, which leads to infinite loop | ||
93 | /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } } | ||
94 | /// We mark it down and skip it in collector | ||
95 | /// | ||
96 | /// FIXME: | ||
97 | /// Right now it only handle a poison macro in a single crate, | ||
98 | /// such that if other crate try to call that macro, | ||
99 | /// the whole process will do again until it became poisoned in that crate. | ||
100 | /// We should handle this macro set globally | ||
101 | /// However, do we want to put it as a global variable? | ||
102 | poison_macros: FxHashSet<MacroDefId>, | ||
103 | 91 | ||
92 | edition: Edition, | ||
104 | diagnostics: Vec<DefDiagnostic>, | 93 | diagnostics: Vec<DefDiagnostic>, |
105 | } | 94 | } |
106 | 95 | ||
107 | impl std::ops::Index<CrateModuleId> for CrateDefMap { | 96 | impl std::ops::Index<LocalModuleId> for CrateDefMap { |
108 | type Output = ModuleData; | 97 | type Output = ModuleData; |
109 | fn index(&self, id: CrateModuleId) -> &ModuleData { | 98 | fn index(&self, id: LocalModuleId) -> &ModuleData { |
110 | &self.modules[id] | 99 | &self.modules[id] |
111 | } | 100 | } |
112 | } | 101 | } |
113 | 102 | ||
114 | #[derive(Default, Debug, PartialEq, Eq)] | 103 | #[derive(Default, Debug, PartialEq, Eq)] |
115 | pub struct ModuleData { | 104 | pub struct ModuleData { |
116 | pub parent: Option<CrateModuleId>, | 105 | pub parent: Option<LocalModuleId>, |
117 | pub children: FxHashMap<Name, CrateModuleId>, | 106 | pub children: FxHashMap<Name, LocalModuleId>, |
118 | pub scope: ModuleScope, | 107 | pub scope: ModuleScope, |
108 | |||
109 | // FIXME: these can't be both null, we need a three-state enum here. | ||
119 | /// None for root | 110 | /// None for root |
120 | pub declaration: Option<AstId<ast::Module>>, | 111 | pub declaration: Option<AstId<ast::Module>>, |
121 | /// None for inline modules. | 112 | /// None for inline modules. |
122 | /// | 113 | /// |
123 | /// Note that non-inline modules, by definition, live inside non-macro file. | 114 | /// Note that non-inline modules, by definition, live inside non-macro file. |
124 | pub definition: Option<FileId>, | 115 | pub definition: Option<FileId>, |
116 | |||
125 | pub impls: Vec<ImplId>, | 117 | pub impls: Vec<ImplId>, |
126 | } | 118 | } |
127 | 119 | ||
@@ -177,7 +169,7 @@ impl ModuleScope { | |||
177 | pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { | 169 | pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { |
178 | self.items | 170 | self.items |
179 | .iter() | 171 | .iter() |
180 | .filter_map(|(name, res)| res.def.get_macros().map(|macro_| (name, macro_))) | 172 | .filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_))) |
181 | } | 173 | } |
182 | 174 | ||
183 | /// Iterate over all legacy textual scoped macros visable at the end of the module | 175 | /// Iterate over all legacy textual scoped macros visable at the end of the module |
@@ -207,21 +199,21 @@ pub struct Resolution { | |||
207 | /// None for unresolved | 199 | /// None for unresolved |
208 | pub def: PerNs, | 200 | pub def: PerNs, |
209 | /// ident by which this is imported into local scope. | 201 | /// ident by which this is imported into local scope. |
210 | pub import: Option<ImportId>, | 202 | pub import: Option<LocalImportId>, |
211 | } | 203 | } |
212 | 204 | ||
213 | impl CrateDefMap { | 205 | impl CrateDefMap { |
214 | pub(crate) fn crate_def_map_query( | 206 | pub(crate) fn crate_def_map_query( |
215 | // Note that this doesn't have `+ AstDatabase`! | 207 | // Note that this doesn't have `+ AstDatabase`! |
216 | // This gurantess that `CrateDefMap` is stable across reparses. | 208 | // This gurantess that `CrateDefMap` is stable across reparses. |
217 | db: &impl DefDatabase2, | 209 | db: &impl DefDatabase, |
218 | krate: CrateId, | 210 | krate: CrateId, |
219 | ) -> Arc<CrateDefMap> { | 211 | ) -> Arc<CrateDefMap> { |
220 | let _p = profile("crate_def_map_query"); | 212 | let _p = profile("crate_def_map_query"); |
221 | let def_map = { | 213 | let def_map = { |
222 | let crate_graph = db.crate_graph(); | 214 | let crate_graph = db.crate_graph(); |
223 | let edition = crate_graph.edition(krate); | 215 | let edition = crate_graph.edition(krate); |
224 | let mut modules: Arena<CrateModuleId, ModuleData> = Arena::default(); | 216 | let mut modules: Arena<LocalModuleId, ModuleData> = Arena::default(); |
225 | let root = modules.alloc(ModuleData::default()); | 217 | let root = modules.alloc(ModuleData::default()); |
226 | CrateDefMap { | 218 | CrateDefMap { |
227 | krate, | 219 | krate, |
@@ -230,7 +222,6 @@ impl CrateDefMap { | |||
230 | prelude: None, | 222 | prelude: None, |
231 | root, | 223 | root, |
232 | modules, | 224 | modules, |
233 | poison_macros: FxHashSet::default(), | ||
234 | diagnostics: Vec::new(), | 225 | diagnostics: Vec::new(), |
235 | } | 226 | } |
236 | }; | 227 | }; |
@@ -238,50 +229,53 @@ impl CrateDefMap { | |||
238 | Arc::new(def_map) | 229 | Arc::new(def_map) |
239 | } | 230 | } |
240 | 231 | ||
241 | pub fn krate(&self) -> CrateId { | ||
242 | self.krate | ||
243 | } | ||
244 | |||
245 | pub fn root(&self) -> CrateModuleId { | ||
246 | self.root | ||
247 | } | ||
248 | |||
249 | pub fn prelude(&self) -> Option<ModuleId> { | ||
250 | self.prelude | ||
251 | } | ||
252 | |||
253 | pub fn extern_prelude(&self) -> &FxHashMap<Name, ModuleDefId> { | ||
254 | &self.extern_prelude | ||
255 | } | ||
256 | |||
257 | pub fn add_diagnostics( | 232 | pub fn add_diagnostics( |
258 | &self, | 233 | &self, |
259 | db: &impl DefDatabase2, | 234 | db: &impl DefDatabase, |
260 | module: CrateModuleId, | 235 | module: LocalModuleId, |
261 | sink: &mut DiagnosticSink, | 236 | sink: &mut DiagnosticSink, |
262 | ) { | 237 | ) { |
263 | self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink)) | 238 | self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink)) |
264 | } | 239 | } |
265 | 240 | ||
266 | pub fn resolve_path( | 241 | pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ { |
242 | self.modules | ||
243 | .iter() | ||
244 | .filter(move |(_id, data)| data.definition == Some(file_id)) | ||
245 | .map(|(id, _data)| id) | ||
246 | } | ||
247 | |||
248 | pub(crate) fn resolve_path( | ||
267 | &self, | 249 | &self, |
268 | db: &impl DefDatabase2, | 250 | db: &impl DefDatabase, |
269 | original_module: CrateModuleId, | 251 | original_module: LocalModuleId, |
270 | path: &Path, | 252 | path: &Path, |
271 | ) -> (PerNs, Option<usize>) { | 253 | ) -> (PerNs, Option<usize>) { |
272 | let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path); | 254 | let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path); |
273 | (res.resolved_def, res.segment_index) | 255 | (res.resolved_def, res.segment_index) |
274 | } | 256 | } |
257 | } | ||
275 | 258 | ||
276 | pub fn modules(&self) -> impl Iterator<Item = CrateModuleId> + '_ { | 259 | impl ModuleData { |
277 | self.modules.iter().map(|(id, _data)| id) | 260 | /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items. |
261 | pub fn definition_source( | ||
262 | &self, | ||
263 | db: &impl DefDatabase, | ||
264 | ) -> Source<Either<ast::SourceFile, ast::Module>> { | ||
265 | if let Some(file_id) = self.definition { | ||
266 | let sf = db.parse(file_id).tree(); | ||
267 | return Source::new(file_id.into(), Either::A(sf)); | ||
268 | } | ||
269 | let decl = self.declaration.unwrap(); | ||
270 | Source::new(decl.file_id(), Either::B(decl.to_node(db))) | ||
278 | } | 271 | } |
279 | 272 | ||
280 | pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = CrateModuleId> + '_ { | 273 | /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. |
281 | self.modules | 274 | /// `None` for the crate root. |
282 | .iter() | 275 | pub fn declaration_source(&self, db: &impl DefDatabase) -> Option<Source<ast::Module>> { |
283 | .filter(move |(_id, data)| data.definition == Some(file_id)) | 276 | let decl = self.declaration?; |
284 | .map(|(id, _data)| id) | 277 | let value = decl.to_node(db); |
278 | Some(Source { file_id: decl.file_id(), value }) | ||
285 | } | 279 | } |
286 | } | 280 | } |
287 | 281 | ||
@@ -290,12 +284,12 @@ mod diagnostics { | |||
290 | use ra_db::RelativePathBuf; | 284 | use ra_db::RelativePathBuf; |
291 | use ra_syntax::{ast, AstPtr}; | 285 | use ra_syntax::{ast, AstPtr}; |
292 | 286 | ||
293 | use crate::{db::DefDatabase2, diagnostics::UnresolvedModule, nameres::CrateModuleId, AstId}; | 287 | use crate::{db::DefDatabase, diagnostics::UnresolvedModule, nameres::LocalModuleId, AstId}; |
294 | 288 | ||
295 | #[derive(Debug, PartialEq, Eq)] | 289 | #[derive(Debug, PartialEq, Eq)] |
296 | pub(super) enum DefDiagnostic { | 290 | pub(super) enum DefDiagnostic { |
297 | UnresolvedModule { | 291 | UnresolvedModule { |
298 | module: CrateModuleId, | 292 | module: LocalModuleId, |
299 | declaration: AstId<ast::Module>, | 293 | declaration: AstId<ast::Module>, |
300 | candidate: RelativePathBuf, | 294 | candidate: RelativePathBuf, |
301 | }, | 295 | }, |
@@ -304,8 +298,8 @@ mod diagnostics { | |||
304 | impl DefDiagnostic { | 298 | impl DefDiagnostic { |
305 | pub(super) fn add_to( | 299 | pub(super) fn add_to( |
306 | &self, | 300 | &self, |
307 | db: &impl DefDatabase2, | 301 | db: &impl DefDatabase, |
308 | target_module: CrateModuleId, | 302 | target_module: LocalModuleId, |
309 | sink: &mut DiagnosticSink, | 303 | sink: &mut DiagnosticSink, |
310 | ) { | 304 | ) { |
311 | match self { | 305 | match self { |