aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/nameres.rs
diff options
context:
space:
mode:
authorSeivan Heidari <[email protected]>2019-11-25 00:54:54 +0000
committerSeivan Heidari <[email protected]>2019-11-25 00:54:54 +0000
commit15ea338ac991707d330288ba4d1bf5daa0fc75d9 (patch)
tree16aeab28bcdb07d36aae28e3fb4a385614865a48 /crates/ra_hir_def/src/nameres.rs
parenteb7363d167c7a9f7c73cb950b621eb1dce493318 (diff)
parentf7f9757b6b144385ab8ce57b15764473b1f57331 (diff)
Merge branch 'master' of https://github.com/rust-analyzer/rust-analyzer into feature/themes
Diffstat (limited to 'crates/ra_hir_def/src/nameres.rs')
-rw-r--r--crates/ra_hir_def/src/nameres.rs130
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
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,70 +57,63 @@ 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};
65use ra_prof::profile; 67use ra_prof::profile;
66use ra_syntax::ast; 68use ra_syntax::ast;
67use rustc_hash::{FxHashMap, FxHashSet}; 69use rustc_hash::FxHashMap;
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
80#[derive(Debug, PartialEq, Eq)] 81#[derive(Debug, PartialEq, Eq)]
81pub struct CrateDefMap { 82pub 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
107impl std::ops::Index<CrateModuleId> for CrateDefMap { 96impl 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)]
115pub struct ModuleData { 104pub 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
213impl CrateDefMap { 205impl 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> + '_ { 259impl 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 {