aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/nameres.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src/nameres.rs')
-rw-r--r--crates/ra_hir_def/src/nameres.rs83
1 files changed, 55 insertions, 28 deletions
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs
index c01e020ef..3b2e99647 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
50pub mod raw; 50pub(crate) mod raw;
51pub mod per_ns;
52mod collector; 51mod collector;
53mod mod_resolution; 52mod mod_resolution;
54mod path_resolution; 53mod path_resolution;
@@ -58,7 +57,10 @@ mod tests;
58 57
59use std::sync::Arc; 58use std::sync::Arc;
60 59
61use hir_expand::{ast_id_map::FileAstId, diagnostics::DiagnosticSink, name::Name, MacroDefId}; 60use hir_expand::{
61 ast_id_map::FileAstId, diagnostics::DiagnosticSink, either::Either, name::Name, MacroDefId,
62 Source,
63};
62use once_cell::sync::Lazy; 64use once_cell::sync::Lazy;
63use ra_arena::Arena; 65use ra_arena::Arena;
64use ra_db::{CrateId, Edition, FileId}; 66use ra_db::{CrateId, Edition, FileId};
@@ -68,12 +70,11 @@ use rustc_hash::{FxHashMap, FxHashSet};
68 70
69use crate::{ 71use 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
@@ -86,8 +87,8 @@ pub struct CrateDefMap {
86 /// a dependency (`std` or `core`). 87 /// a dependency (`std` or `core`).
87 prelude: Option<ModuleId>, 88 prelude: Option<ModuleId>,
88 extern_prelude: FxHashMap<Name, ModuleDefId>, 89 extern_prelude: FxHashMap<Name, ModuleDefId>,
89 root: CrateModuleId, 90 root: LocalModuleId,
90 modules: Arena<CrateModuleId, ModuleData>, 91 modules: Arena<LocalModuleId, ModuleData>,
91 92
92 /// Some macros are not well-behavior, which leads to infinite loop 93 /// Some macros are not well-behavior, which leads to infinite loop
93 /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } } 94 /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } }
@@ -104,24 +105,27 @@ pub struct CrateDefMap {
104 diagnostics: Vec<DefDiagnostic>, 105 diagnostics: Vec<DefDiagnostic>,
105} 106}
106 107
107impl std::ops::Index<CrateModuleId> for CrateDefMap { 108impl std::ops::Index<LocalModuleId> for CrateDefMap {
108 type Output = ModuleData; 109 type Output = ModuleData;
109 fn index(&self, id: CrateModuleId) -> &ModuleData { 110 fn index(&self, id: LocalModuleId) -> &ModuleData {
110 &self.modules[id] 111 &self.modules[id]
111 } 112 }
112} 113}
113 114
114#[derive(Default, Debug, PartialEq, Eq)] 115#[derive(Default, Debug, PartialEq, Eq)]
115pub struct ModuleData { 116pub struct ModuleData {
116 pub parent: Option<CrateModuleId>, 117 pub parent: Option<LocalModuleId>,
117 pub children: FxHashMap<Name, CrateModuleId>, 118 pub children: FxHashMap<Name, LocalModuleId>,
118 pub scope: ModuleScope, 119 pub scope: ModuleScope,
120
121 // FIXME: these can't be both null, we need a three-state enum here.
119 /// None for root 122 /// None for root
120 pub declaration: Option<AstId<ast::Module>>, 123 pub declaration: Option<AstId<ast::Module>>,
121 /// None for inline modules. 124 /// None for inline modules.
122 /// 125 ///
123 /// Note that non-inline modules, by definition, live inside non-macro file. 126 /// Note that non-inline modules, by definition, live inside non-macro file.
124 pub definition: Option<FileId>, 127 pub definition: Option<FileId>,
128
125 pub impls: Vec<ImplId>, 129 pub impls: Vec<ImplId>,
126} 130}
127 131
@@ -207,21 +211,21 @@ pub struct Resolution {
207 /// None for unresolved 211 /// None for unresolved
208 pub def: PerNs, 212 pub def: PerNs,
209 /// ident by which this is imported into local scope. 213 /// ident by which this is imported into local scope.
210 pub import: Option<ImportId>, 214 pub import: Option<LocalImportId>,
211} 215}
212 216
213impl CrateDefMap { 217impl CrateDefMap {
214 pub(crate) fn crate_def_map_query( 218 pub(crate) fn crate_def_map_query(
215 // Note that this doesn't have `+ AstDatabase`! 219 // Note that this doesn't have `+ AstDatabase`!
216 // This gurantess that `CrateDefMap` is stable across reparses. 220 // This gurantess that `CrateDefMap` is stable across reparses.
217 db: &impl DefDatabase2, 221 db: &impl DefDatabase,
218 krate: CrateId, 222 krate: CrateId,
219 ) -> Arc<CrateDefMap> { 223 ) -> Arc<CrateDefMap> {
220 let _p = profile("crate_def_map_query"); 224 let _p = profile("crate_def_map_query");
221 let def_map = { 225 let def_map = {
222 let crate_graph = db.crate_graph(); 226 let crate_graph = db.crate_graph();
223 let edition = crate_graph.edition(krate); 227 let edition = crate_graph.edition(krate);
224 let mut modules: Arena<CrateModuleId, ModuleData> = Arena::default(); 228 let mut modules: Arena<LocalModuleId, ModuleData> = Arena::default();
225 let root = modules.alloc(ModuleData::default()); 229 let root = modules.alloc(ModuleData::default());
226 CrateDefMap { 230 CrateDefMap {
227 krate, 231 krate,
@@ -242,7 +246,7 @@ impl CrateDefMap {
242 self.krate 246 self.krate
243 } 247 }
244 248
245 pub fn root(&self) -> CrateModuleId { 249 pub fn root(&self) -> LocalModuleId {
246 self.root 250 self.root
247 } 251 }
248 252
@@ -256,8 +260,8 @@ impl CrateDefMap {
256 260
257 pub fn add_diagnostics( 261 pub fn add_diagnostics(
258 &self, 262 &self,
259 db: &impl DefDatabase2, 263 db: &impl DefDatabase,
260 module: CrateModuleId, 264 module: LocalModuleId,
261 sink: &mut DiagnosticSink, 265 sink: &mut DiagnosticSink,
262 ) { 266 ) {
263 self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink)) 267 self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink))
@@ -265,19 +269,19 @@ impl CrateDefMap {
265 269
266 pub fn resolve_path( 270 pub fn resolve_path(
267 &self, 271 &self,
268 db: &impl DefDatabase2, 272 db: &impl DefDatabase,
269 original_module: CrateModuleId, 273 original_module: LocalModuleId,
270 path: &Path, 274 path: &Path,
271 ) -> (PerNs, Option<usize>) { 275 ) -> (PerNs, Option<usize>) {
272 let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path); 276 let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path);
273 (res.resolved_def, res.segment_index) 277 (res.resolved_def, res.segment_index)
274 } 278 }
275 279
276 pub fn modules(&self) -> impl Iterator<Item = CrateModuleId> + '_ { 280 pub fn modules(&self) -> impl Iterator<Item = LocalModuleId> + '_ {
277 self.modules.iter().map(|(id, _data)| id) 281 self.modules.iter().map(|(id, _data)| id)
278 } 282 }
279 283
280 pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = CrateModuleId> + '_ { 284 pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ {
281 self.modules 285 self.modules
282 .iter() 286 .iter()
283 .filter(move |(_id, data)| data.definition == Some(file_id)) 287 .filter(move |(_id, data)| data.definition == Some(file_id))
@@ -285,17 +289,40 @@ impl CrateDefMap {
285 } 289 }
286} 290}
287 291
292impl ModuleData {
293 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
294 pub fn definition_source(
295 &self,
296 db: &impl DefDatabase,
297 ) -> Source<Either<ast::SourceFile, ast::Module>> {
298 if let Some(file_id) = self.definition {
299 let sf = db.parse(file_id).tree();
300 return Source::new(file_id.into(), Either::A(sf));
301 }
302 let decl = self.declaration.unwrap();
303 Source::new(decl.file_id(), Either::B(decl.to_node(db)))
304 }
305
306 /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
307 /// `None` for the crate root.
308 pub fn declaration_source(&self, db: &impl DefDatabase) -> Option<Source<ast::Module>> {
309 let decl = self.declaration?;
310 let value = decl.to_node(db);
311 Some(Source { file_id: decl.file_id(), value })
312 }
313}
314
288mod diagnostics { 315mod diagnostics {
289 use hir_expand::diagnostics::DiagnosticSink; 316 use hir_expand::diagnostics::DiagnosticSink;
290 use ra_db::RelativePathBuf; 317 use ra_db::RelativePathBuf;
291 use ra_syntax::{ast, AstPtr}; 318 use ra_syntax::{ast, AstPtr};
292 319
293 use crate::{db::DefDatabase2, diagnostics::UnresolvedModule, nameres::CrateModuleId, AstId}; 320 use crate::{db::DefDatabase, diagnostics::UnresolvedModule, nameres::LocalModuleId, AstId};
294 321
295 #[derive(Debug, PartialEq, Eq)] 322 #[derive(Debug, PartialEq, Eq)]
296 pub(super) enum DefDiagnostic { 323 pub(super) enum DefDiagnostic {
297 UnresolvedModule { 324 UnresolvedModule {
298 module: CrateModuleId, 325 module: LocalModuleId,
299 declaration: AstId<ast::Module>, 326 declaration: AstId<ast::Module>,
300 candidate: RelativePathBuf, 327 candidate: RelativePathBuf,
301 }, 328 },
@@ -304,8 +331,8 @@ mod diagnostics {
304 impl DefDiagnostic { 331 impl DefDiagnostic {
305 pub(super) fn add_to( 332 pub(super) fn add_to(
306 &self, 333 &self,
307 db: &impl DefDatabase2, 334 db: &impl DefDatabase,
308 target_module: CrateModuleId, 335 target_module: LocalModuleId,
309 sink: &mut DiagnosticSink, 336 sink: &mut DiagnosticSink,
310 ) { 337 ) {
311 match self { 338 match self {