diff options
Diffstat (limited to 'crates/ra_hir/src/nameres')
-rw-r--r-- | crates/ra_hir/src/nameres/collector.rs (renamed from crates/ra_hir/src/nameres/crate_def_map/collector.rs) | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/crate_def_map.rs | 368 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/lower.rs | 40 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/per_ns.rs | 78 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/raw.rs (renamed from crates/ra_hir/src/nameres/crate_def_map/raw.rs) | 41 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests.rs (renamed from crates/ra_hir/src/nameres/crate_def_map/tests.rs) | 0 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests/globs.rs (renamed from crates/ra_hir/src/nameres/crate_def_map/tests/globs.rs) | 0 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests/incremental.rs (renamed from crates/ra_hir/src/nameres/crate_def_map/tests/incremental.rs) | 0 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests/macros.rs (renamed from crates/ra_hir/src/nameres/crate_def_map/tests/macros.rs) | 0 |
9 files changed, 115 insertions, 416 deletions
diff --git a/crates/ra_hir/src/nameres/crate_def_map/collector.rs b/crates/ra_hir/src/nameres/collector.rs index 0f500ce42..cbe850ba4 100644 --- a/crates/ra_hir/src/nameres/crate_def_map/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs | |||
@@ -8,11 +8,11 @@ use crate::{ | |||
8 | Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias, | 8 | Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias, |
9 | PersistentHirDatabase, HirFileId, Name, Path, Problem, | 9 | PersistentHirDatabase, HirFileId, Name, Path, Problem, |
10 | KnownName, | 10 | KnownName, |
11 | nameres::{Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode}, | 11 | nameres::{Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode, raw}, |
12 | ids::{AstItemDef, LocationCtx, MacroCallLoc, SourceItemId, MacroCallId}, | 12 | ids::{AstItemDef, LocationCtx, MacroCallLoc, SourceItemId, MacroCallId}, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | use super::{CrateDefMap, ModuleId, ModuleData, raw}; | 15 | use super::{CrateDefMap, ModuleId, ModuleData}; |
16 | 16 | ||
17 | pub(super) fn collect_defs( | 17 | pub(super) fn collect_defs( |
18 | db: &impl PersistentHirDatabase, | 18 | db: &impl PersistentHirDatabase, |
diff --git a/crates/ra_hir/src/nameres/crate_def_map.rs b/crates/ra_hir/src/nameres/crate_def_map.rs deleted file mode 100644 index cc4955053..000000000 --- a/crates/ra_hir/src/nameres/crate_def_map.rs +++ /dev/null | |||
@@ -1,368 +0,0 @@ | |||
1 | /// This module implements new import-resolution/macro expansion algorithm. | ||
2 | /// | ||
3 | /// The result of this module is `CrateDefMap`: a datastructure which contains: | ||
4 | /// | ||
5 | /// * a tree of modules for the crate | ||
6 | /// * for each module, a set of items visible in the module (directly declared | ||
7 | /// or imported) | ||
8 | /// | ||
9 | /// Note that `CrateDefMap` contains fully macro expanded code. | ||
10 | /// | ||
11 | /// Computing `CrateDefMap` can be partitioned into several logically | ||
12 | /// independent "phases". The phases are mutually recursive though, there's no | ||
13 | /// stric ordering. | ||
14 | /// | ||
15 | /// ## Collecting RawItems | ||
16 | /// | ||
17 | /// This happens in the `raw` module, which parses a single source file into a | ||
18 | /// set of top-level items. Nested importa are desugared to flat imports in | ||
19 | /// this phase. Macro calls are represented as a triple of (Path, Option<Name>, | ||
20 | /// TokenTree). | ||
21 | /// | ||
22 | /// ## Collecting Modules | ||
23 | /// | ||
24 | /// This happens in the `collector` module. In this phase, we recursively walk | ||
25 | /// tree of modules, collect raw items from submodules, populate module scopes | ||
26 | /// with defined items (so, we assign item ids in this phase) and record the set | ||
27 | /// of unresovled imports and macros. | ||
28 | /// | ||
29 | /// While we walk tree of modules, we also record macro_rules defenitions and | ||
30 | /// expand calls to macro_rules defined macros. | ||
31 | /// | ||
32 | /// ## Resolving Imports | ||
33 | /// | ||
34 | /// TBD | ||
35 | /// | ||
36 | /// ## Resolving Macros | ||
37 | /// | ||
38 | /// While macro_rules from the same crate use a global mutable namespace, macros | ||
39 | /// from other crates (including proc-macros) can be used with `foo::bar!` | ||
40 | /// syntax. | ||
41 | /// | ||
42 | /// TBD; | ||
43 | |||
44 | mod raw; | ||
45 | mod collector; | ||
46 | #[cfg(test)] | ||
47 | mod tests; | ||
48 | |||
49 | use rustc_hash::FxHashMap; | ||
50 | use test_utils::tested_by; | ||
51 | use ra_arena::{Arena, RawId, impl_arena_id}; | ||
52 | use ra_db::FileId; | ||
53 | |||
54 | use std::sync::Arc; | ||
55 | |||
56 | use crate::{ | ||
57 | Name, Module, Path, PathKind, ModuleDef, Crate, Problem, HirFileId, | ||
58 | PersistentHirDatabase, | ||
59 | nameres::{ModuleScope, ResolveMode, ResolvePathResult, PerNs, Edition, ReachedFixedPoint}, | ||
60 | ids::{SourceItemId, SourceFileItemId}, | ||
61 | }; | ||
62 | |||
63 | pub(crate) use self::raw::RawItems; | ||
64 | |||
65 | #[derive(Default, Debug, PartialEq, Eq)] | ||
66 | pub(crate) struct ModuleData { | ||
67 | pub(crate) parent: Option<ModuleId>, | ||
68 | pub(crate) children: FxHashMap<Name, ModuleId>, | ||
69 | pub(crate) scope: ModuleScope, | ||
70 | /// None for root | ||
71 | pub(crate) declaration: Option<SourceItemId>, | ||
72 | /// None for inline modules. | ||
73 | /// | ||
74 | /// Note that non-inline modules, by definition, live inside non-macro file. | ||
75 | pub(crate) definition: Option<FileId>, | ||
76 | } | ||
77 | |||
78 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||
79 | pub(crate) struct ModuleId(RawId); | ||
80 | impl_arena_id!(ModuleId); | ||
81 | |||
82 | /// Contans all top-level defs from a macro-expanded crate | ||
83 | #[derive(Debug, PartialEq, Eq)] | ||
84 | pub struct CrateDefMap { | ||
85 | krate: Crate, | ||
86 | edition: Edition, | ||
87 | /// The prelude module for this crate. This either comes from an import | ||
88 | /// marked with the `prelude_import` attribute, or (in the normal case) from | ||
89 | /// a dependency (`std` or `core`). | ||
90 | prelude: Option<Module>, | ||
91 | extern_prelude: FxHashMap<Name, ModuleDef>, | ||
92 | root: ModuleId, | ||
93 | modules: Arena<ModuleId, ModuleData>, | ||
94 | public_macros: FxHashMap<Name, mbe::MacroRules>, | ||
95 | problems: CrateDefMapProblems, | ||
96 | } | ||
97 | |||
98 | #[derive(Default, Debug, PartialEq, Eq)] | ||
99 | pub(crate) struct CrateDefMapProblems { | ||
100 | problems: Vec<(SourceItemId, Problem)>, | ||
101 | } | ||
102 | |||
103 | impl CrateDefMapProblems { | ||
104 | fn add(&mut self, source_item_id: SourceItemId, problem: Problem) { | ||
105 | self.problems.push((source_item_id, problem)) | ||
106 | } | ||
107 | |||
108 | pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = (&'a SourceItemId, &'a Problem)> + 'a { | ||
109 | self.problems.iter().map(|(s, p)| (s, p)) | ||
110 | } | ||
111 | } | ||
112 | |||
113 | impl std::ops::Index<ModuleId> for CrateDefMap { | ||
114 | type Output = ModuleData; | ||
115 | fn index(&self, id: ModuleId) -> &ModuleData { | ||
116 | &self.modules[id] | ||
117 | } | ||
118 | } | ||
119 | |||
120 | impl CrateDefMap { | ||
121 | pub(crate) fn crate_def_map_query( | ||
122 | db: &impl PersistentHirDatabase, | ||
123 | krate: Crate, | ||
124 | ) -> Arc<CrateDefMap> { | ||
125 | let def_map = { | ||
126 | let edition = krate.edition(db); | ||
127 | let mut modules: Arena<ModuleId, ModuleData> = Arena::default(); | ||
128 | let root = modules.alloc(ModuleData::default()); | ||
129 | CrateDefMap { | ||
130 | krate, | ||
131 | edition, | ||
132 | extern_prelude: FxHashMap::default(), | ||
133 | prelude: None, | ||
134 | root, | ||
135 | modules, | ||
136 | public_macros: FxHashMap::default(), | ||
137 | problems: CrateDefMapProblems::default(), | ||
138 | } | ||
139 | }; | ||
140 | let def_map = collector::collect_defs(db, def_map); | ||
141 | Arc::new(def_map) | ||
142 | } | ||
143 | |||
144 | pub(crate) fn root(&self) -> ModuleId { | ||
145 | self.root | ||
146 | } | ||
147 | |||
148 | pub(crate) fn problems(&self) -> &CrateDefMapProblems { | ||
149 | &self.problems | ||
150 | } | ||
151 | |||
152 | pub(crate) fn mk_module(&self, module_id: ModuleId) -> Module { | ||
153 | Module { krate: self.krate, module_id } | ||
154 | } | ||
155 | |||
156 | pub(crate) fn prelude(&self) -> Option<Module> { | ||
157 | self.prelude | ||
158 | } | ||
159 | |||
160 | pub(crate) fn extern_prelude(&self) -> &FxHashMap<Name, ModuleDef> { | ||
161 | &self.extern_prelude | ||
162 | } | ||
163 | |||
164 | pub(crate) fn find_module_by_source( | ||
165 | &self, | ||
166 | file_id: HirFileId, | ||
167 | decl_id: Option<SourceFileItemId>, | ||
168 | ) -> Option<ModuleId> { | ||
169 | let decl_id = decl_id.map(|it| it.with_file_id(file_id)); | ||
170 | let (module_id, _module_data) = self.modules.iter().find(|(_module_id, module_data)| { | ||
171 | if decl_id.is_some() { | ||
172 | module_data.declaration == decl_id | ||
173 | } else { | ||
174 | module_data.definition.map(|it| it.into()) == Some(file_id) | ||
175 | } | ||
176 | })?; | ||
177 | Some(module_id) | ||
178 | } | ||
179 | |||
180 | pub(crate) fn resolve_path( | ||
181 | &self, | ||
182 | db: &impl PersistentHirDatabase, | ||
183 | original_module: ModuleId, | ||
184 | path: &Path, | ||
185 | ) -> (PerNs<ModuleDef>, Option<usize>) { | ||
186 | let res = self.resolve_path_fp(db, ResolveMode::Other, original_module, path); | ||
187 | (res.resolved_def, res.segment_index) | ||
188 | } | ||
189 | |||
190 | // Returns Yes if we are sure that additions to `ItemMap` wouldn't change | ||
191 | // the result. | ||
192 | fn resolve_path_fp( | ||
193 | &self, | ||
194 | db: &impl PersistentHirDatabase, | ||
195 | mode: ResolveMode, | ||
196 | original_module: ModuleId, | ||
197 | path: &Path, | ||
198 | ) -> ResolvePathResult { | ||
199 | let mut segments = path.segments.iter().enumerate(); | ||
200 | let mut curr_per_ns: PerNs<ModuleDef> = match path.kind { | ||
201 | PathKind::Crate => { | ||
202 | PerNs::types(Module { krate: self.krate, module_id: self.root }.into()) | ||
203 | } | ||
204 | PathKind::Self_ => { | ||
205 | PerNs::types(Module { krate: self.krate, module_id: original_module }.into()) | ||
206 | } | ||
207 | // plain import or absolute path in 2015: crate-relative with | ||
208 | // fallback to extern prelude (with the simplification in | ||
209 | // rust-lang/rust#57745) | ||
210 | // TODO there must be a nicer way to write this condition | ||
211 | PathKind::Plain | PathKind::Abs | ||
212 | if self.edition == Edition::Edition2015 | ||
213 | && (path.kind == PathKind::Abs || mode == ResolveMode::Import) => | ||
214 | { | ||
215 | let segment = match segments.next() { | ||
216 | Some((_, segment)) => segment, | ||
217 | None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), | ||
218 | }; | ||
219 | log::debug!("resolving {:?} in crate root (+ extern prelude)", segment); | ||
220 | self.resolve_name_in_crate_root_or_extern_prelude(&segment.name) | ||
221 | } | ||
222 | PathKind::Plain => { | ||
223 | let segment = match segments.next() { | ||
224 | Some((_, segment)) => segment, | ||
225 | None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), | ||
226 | }; | ||
227 | log::debug!("resolving {:?} in module", segment); | ||
228 | self.resolve_name_in_module(db, original_module, &segment.name) | ||
229 | } | ||
230 | PathKind::Super => { | ||
231 | if let Some(p) = self.modules[original_module].parent { | ||
232 | PerNs::types(Module { krate: self.krate, module_id: p }.into()) | ||
233 | } else { | ||
234 | log::debug!("super path in root module"); | ||
235 | return ResolvePathResult::empty(ReachedFixedPoint::Yes); | ||
236 | } | ||
237 | } | ||
238 | PathKind::Abs => { | ||
239 | // 2018-style absolute path -- only extern prelude | ||
240 | let segment = match segments.next() { | ||
241 | Some((_, segment)) => segment, | ||
242 | None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), | ||
243 | }; | ||
244 | if let Some(def) = self.extern_prelude.get(&segment.name) { | ||
245 | log::debug!("absolute path {:?} resolved to crate {:?}", path, def); | ||
246 | PerNs::types(*def) | ||
247 | } else { | ||
248 | return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude | ||
249 | } | ||
250 | } | ||
251 | }; | ||
252 | |||
253 | for (i, segment) in segments { | ||
254 | let curr = match curr_per_ns.as_ref().take_types() { | ||
255 | Some(r) => r, | ||
256 | None => { | ||
257 | // we still have path segments left, but the path so far | ||
258 | // didn't resolve in the types namespace => no resolution | ||
259 | // (don't break here because `curr_per_ns` might contain | ||
260 | // something in the value namespace, and it would be wrong | ||
261 | // to return that) | ||
262 | return ResolvePathResult::empty(ReachedFixedPoint::No); | ||
263 | } | ||
264 | }; | ||
265 | // resolve segment in curr | ||
266 | |||
267 | curr_per_ns = match curr { | ||
268 | ModuleDef::Module(module) => { | ||
269 | if module.krate != self.krate { | ||
270 | let path = Path { | ||
271 | segments: path.segments[i..].iter().cloned().collect(), | ||
272 | kind: PathKind::Self_, | ||
273 | }; | ||
274 | log::debug!("resolving {:?} in other crate", path); | ||
275 | let defp_map = db.crate_def_map(module.krate); | ||
276 | let (def, s) = defp_map.resolve_path(db, module.module_id, &path); | ||
277 | return ResolvePathResult::with( | ||
278 | def, | ||
279 | ReachedFixedPoint::Yes, | ||
280 | s.map(|s| s + i), | ||
281 | ); | ||
282 | } | ||
283 | |||
284 | match self[module.module_id].scope.items.get(&segment.name) { | ||
285 | Some(res) if !res.def.is_none() => res.def, | ||
286 | _ => { | ||
287 | log::debug!("path segment {:?} not found", segment.name); | ||
288 | return ResolvePathResult::empty(ReachedFixedPoint::No); | ||
289 | } | ||
290 | } | ||
291 | } | ||
292 | ModuleDef::Enum(e) => { | ||
293 | // enum variant | ||
294 | tested_by!(can_import_enum_variant); | ||
295 | match e.variant(db, &segment.name) { | ||
296 | Some(variant) => PerNs::both(variant.into(), variant.into()), | ||
297 | None => { | ||
298 | return ResolvePathResult::with( | ||
299 | PerNs::types((*e).into()), | ||
300 | ReachedFixedPoint::Yes, | ||
301 | Some(i), | ||
302 | ); | ||
303 | } | ||
304 | } | ||
305 | } | ||
306 | s => { | ||
307 | // could be an inherent method call in UFCS form | ||
308 | // (`Struct::method`), or some other kind of associated item | ||
309 | log::debug!( | ||
310 | "path segment {:?} resolved to non-module {:?}, but is not last", | ||
311 | segment.name, | ||
312 | curr, | ||
313 | ); | ||
314 | |||
315 | return ResolvePathResult::with( | ||
316 | PerNs::types((*s).into()), | ||
317 | ReachedFixedPoint::Yes, | ||
318 | Some(i), | ||
319 | ); | ||
320 | } | ||
321 | }; | ||
322 | } | ||
323 | ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None) | ||
324 | } | ||
325 | |||
326 | fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> { | ||
327 | let from_crate_root = | ||
328 | self[self.root].scope.items.get(name).map_or(PerNs::none(), |it| it.def); | ||
329 | let from_extern_prelude = self.resolve_name_in_extern_prelude(name); | ||
330 | |||
331 | from_crate_root.or(from_extern_prelude) | ||
332 | } | ||
333 | |||
334 | pub(crate) fn resolve_name_in_module( | ||
335 | &self, | ||
336 | db: &impl PersistentHirDatabase, | ||
337 | module: ModuleId, | ||
338 | name: &Name, | ||
339 | ) -> PerNs<ModuleDef> { | ||
340 | // Resolve in: | ||
341 | // - current module / scope | ||
342 | // - extern prelude | ||
343 | // - std prelude | ||
344 | let from_scope = self[module].scope.items.get(name).map_or(PerNs::none(), |it| it.def); | ||
345 | let from_extern_prelude = | ||
346 | self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); | ||
347 | let from_prelude = self.resolve_in_prelude(db, name); | ||
348 | |||
349 | from_scope.or(from_extern_prelude).or(from_prelude) | ||
350 | } | ||
351 | |||
352 | fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> { | ||
353 | self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)) | ||
354 | } | ||
355 | |||
356 | fn resolve_in_prelude(&self, db: &impl PersistentHirDatabase, name: &Name) -> PerNs<ModuleDef> { | ||
357 | if let Some(prelude) = self.prelude { | ||
358 | let resolution = if prelude.krate == self.krate { | ||
359 | self[prelude.module_id].scope.items.get(name).cloned() | ||
360 | } else { | ||
361 | db.crate_def_map(prelude.krate)[prelude.module_id].scope.items.get(name).cloned() | ||
362 | }; | ||
363 | resolution.map(|r| r.def).unwrap_or_else(PerNs::none) | ||
364 | } else { | ||
365 | PerNs::none() | ||
366 | } | ||
367 | } | ||
368 | } | ||
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs deleted file mode 100644 index d4c7f2481..000000000 --- a/crates/ra_hir/src/nameres/lower.rs +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | use ra_syntax::{ | ||
2 | AstNode, SourceFile, TreeArc, AstPtr, | ||
3 | ast, | ||
4 | }; | ||
5 | use ra_arena::{RawId, impl_arena_id, map::ArenaMap}; | ||
6 | |||
7 | use crate::{Path, ModuleSource, Name}; | ||
8 | |||
9 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
10 | pub struct ImportId(RawId); | ||
11 | impl_arena_id!(ImportId); | ||
12 | |||
13 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
14 | pub struct ImportData { | ||
15 | pub(super) path: Path, | ||
16 | pub(super) alias: Option<Name>, | ||
17 | pub(super) is_glob: bool, | ||
18 | pub(super) is_prelude: bool, | ||
19 | pub(super) is_extern_crate: bool, | ||
20 | } | ||
21 | |||
22 | #[derive(Debug, Default, PartialEq, Eq)] | ||
23 | pub struct ImportSourceMap { | ||
24 | map: ArenaMap<ImportId, AstPtr<ast::PathSegment>>, | ||
25 | } | ||
26 | |||
27 | impl ImportSourceMap { | ||
28 | pub(crate) fn insert(&mut self, import: ImportId, segment: &ast::PathSegment) { | ||
29 | self.map.insert(import, AstPtr::new(segment)) | ||
30 | } | ||
31 | |||
32 | pub fn get(&self, source: &ModuleSource, import: ImportId) -> TreeArc<ast::PathSegment> { | ||
33 | let file = match source { | ||
34 | ModuleSource::SourceFile(file) => &*file, | ||
35 | ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(), | ||
36 | }; | ||
37 | |||
38 | self.map[import].to_node(file).to_owned() | ||
39 | } | ||
40 | } | ||
diff --git a/crates/ra_hir/src/nameres/per_ns.rs b/crates/ra_hir/src/nameres/per_ns.rs new file mode 100644 index 000000000..c40a3ff9d --- /dev/null +++ b/crates/ra_hir/src/nameres/per_ns.rs | |||
@@ -0,0 +1,78 @@ | |||
1 | #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||
2 | pub enum Namespace { | ||
3 | Types, | ||
4 | Values, | ||
5 | } | ||
6 | |||
7 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | ||
8 | pub struct PerNs<T> { | ||
9 | pub types: Option<T>, | ||
10 | pub values: Option<T>, | ||
11 | } | ||
12 | |||
13 | impl<T> Default for PerNs<T> { | ||
14 | fn default() -> Self { | ||
15 | PerNs { types: None, values: None } | ||
16 | } | ||
17 | } | ||
18 | |||
19 | impl<T> PerNs<T> { | ||
20 | pub fn none() -> PerNs<T> { | ||
21 | PerNs { types: None, values: None } | ||
22 | } | ||
23 | |||
24 | pub fn values(t: T) -> PerNs<T> { | ||
25 | PerNs { types: None, values: Some(t) } | ||
26 | } | ||
27 | |||
28 | pub fn types(t: T) -> PerNs<T> { | ||
29 | PerNs { types: Some(t), values: None } | ||
30 | } | ||
31 | |||
32 | pub fn both(types: T, values: T) -> PerNs<T> { | ||
33 | PerNs { types: Some(types), values: Some(values) } | ||
34 | } | ||
35 | |||
36 | pub fn is_none(&self) -> bool { | ||
37 | self.types.is_none() && self.values.is_none() | ||
38 | } | ||
39 | |||
40 | pub fn is_both(&self) -> bool { | ||
41 | self.types.is_some() && self.values.is_some() | ||
42 | } | ||
43 | |||
44 | pub fn take(self, namespace: Namespace) -> Option<T> { | ||
45 | match namespace { | ||
46 | Namespace::Types => self.types, | ||
47 | Namespace::Values => self.values, | ||
48 | } | ||
49 | } | ||
50 | |||
51 | pub fn take_types(self) -> Option<T> { | ||
52 | self.take(Namespace::Types) | ||
53 | } | ||
54 | |||
55 | pub fn take_values(self) -> Option<T> { | ||
56 | self.take(Namespace::Values) | ||
57 | } | ||
58 | |||
59 | pub fn get(&self, namespace: Namespace) -> Option<&T> { | ||
60 | self.as_ref().take(namespace) | ||
61 | } | ||
62 | |||
63 | pub fn as_ref(&self) -> PerNs<&T> { | ||
64 | PerNs { types: self.types.as_ref(), values: self.values.as_ref() } | ||
65 | } | ||
66 | |||
67 | pub fn or(self, other: PerNs<T>) -> PerNs<T> { | ||
68 | PerNs { types: self.types.or(other.types), values: self.values.or(other.values) } | ||
69 | } | ||
70 | |||
71 | pub fn and_then<U>(self, f: impl Fn(T) -> Option<U>) -> PerNs<U> { | ||
72 | PerNs { types: self.types.and_then(&f), values: self.values.and_then(&f) } | ||
73 | } | ||
74 | |||
75 | pub fn map<U>(self, f: impl Fn(T) -> U) -> PerNs<U> { | ||
76 | PerNs { types: self.types.map(&f), values: self.values.map(&f) } | ||
77 | } | ||
78 | } | ||
diff --git a/crates/ra_hir/src/nameres/crate_def_map/raw.rs b/crates/ra_hir/src/nameres/raw.rs index dca86e394..3226bbf0d 100644 --- a/crates/ra_hir/src/nameres/crate_def_map/raw.rs +++ b/crates/ra_hir/src/nameres/raw.rs | |||
@@ -5,16 +5,15 @@ use std::{ | |||
5 | 5 | ||
6 | use test_utils::tested_by; | 6 | use test_utils::tested_by; |
7 | use ra_db::FileId; | 7 | use ra_db::FileId; |
8 | use ra_arena::{Arena, impl_arena_id, RawId}; | 8 | use ra_arena::{Arena, impl_arena_id, RawId, map::ArenaMap}; |
9 | use ra_syntax::{ | 9 | use ra_syntax::{ |
10 | AstNode, SourceFile, | 10 | AstNode, SourceFile, AstPtr, TreeArc, |
11 | ast::{self, NameOwner, AttrsOwner}, | 11 | ast::{self, NameOwner, AttrsOwner}, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | use crate::{ | 14 | use crate::{ |
15 | PersistentHirDatabase, Name, AsName, Path, HirFileId, | 15 | PersistentHirDatabase, Name, AsName, Path, HirFileId, ModuleSource, |
16 | ids::{SourceFileItemId, SourceFileItems}, | 16 | ids::{SourceFileItemId, SourceFileItems}, |
17 | nameres::lower::ImportSourceMap, | ||
18 | }; | 17 | }; |
19 | 18 | ||
20 | #[derive(Debug, Default, PartialEq, Eq)] | 19 | #[derive(Debug, Default, PartialEq, Eq)] |
@@ -27,6 +26,26 @@ pub struct RawItems { | |||
27 | items: Vec<RawItem>, | 26 | items: Vec<RawItem>, |
28 | } | 27 | } |
29 | 28 | ||
29 | #[derive(Debug, Default, PartialEq, Eq)] | ||
30 | pub struct ImportSourceMap { | ||
31 | map: ArenaMap<ImportId, AstPtr<ast::PathSegment>>, | ||
32 | } | ||
33 | |||
34 | impl ImportSourceMap { | ||
35 | pub(crate) fn insert(&mut self, import: ImportId, segment: &ast::PathSegment) { | ||
36 | self.map.insert(import, AstPtr::new(segment)) | ||
37 | } | ||
38 | |||
39 | pub fn get(&self, source: &ModuleSource, import: ImportId) -> TreeArc<ast::PathSegment> { | ||
40 | let file = match source { | ||
41 | ModuleSource::SourceFile(file) => &*file, | ||
42 | ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(), | ||
43 | }; | ||
44 | |||
45 | self.map[import].to_node(file).to_owned() | ||
46 | } | ||
47 | } | ||
48 | |||
30 | impl RawItems { | 49 | impl RawItems { |
31 | pub(crate) fn raw_items_query( | 50 | pub(crate) fn raw_items_query( |
32 | db: &impl PersistentHirDatabase, | 51 | db: &impl PersistentHirDatabase, |
@@ -113,8 +132,18 @@ pub(crate) enum ModuleData { | |||
113 | Definition { name: Name, source_item_id: SourceFileItemId, items: Vec<RawItem> }, | 132 | Definition { name: Name, source_item_id: SourceFileItemId, items: Vec<RawItem> }, |
114 | } | 133 | } |
115 | 134 | ||
116 | pub(crate) use crate::nameres::lower::ImportId; | 135 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
117 | pub(super) use crate::nameres::lower::ImportData; | 136 | pub struct ImportId(RawId); |
137 | impl_arena_id!(ImportId); | ||
138 | |||
139 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
140 | pub struct ImportData { | ||
141 | pub(crate) path: Path, | ||
142 | pub(crate) alias: Option<Name>, | ||
143 | pub(crate) is_glob: bool, | ||
144 | pub(crate) is_prelude: bool, | ||
145 | pub(crate) is_extern_crate: bool, | ||
146 | } | ||
118 | 147 | ||
119 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 148 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
120 | pub(crate) struct Def(RawId); | 149 | pub(crate) struct Def(RawId); |
diff --git a/crates/ra_hir/src/nameres/crate_def_map/tests.rs b/crates/ra_hir/src/nameres/tests.rs index 36c1d74ce..36c1d74ce 100644 --- a/crates/ra_hir/src/nameres/crate_def_map/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs | |||
diff --git a/crates/ra_hir/src/nameres/crate_def_map/tests/globs.rs b/crates/ra_hir/src/nameres/tests/globs.rs index 6e50c7ff6..6e50c7ff6 100644 --- a/crates/ra_hir/src/nameres/crate_def_map/tests/globs.rs +++ b/crates/ra_hir/src/nameres/tests/globs.rs | |||
diff --git a/crates/ra_hir/src/nameres/crate_def_map/tests/incremental.rs b/crates/ra_hir/src/nameres/tests/incremental.rs index 698781923..698781923 100644 --- a/crates/ra_hir/src/nameres/crate_def_map/tests/incremental.rs +++ b/crates/ra_hir/src/nameres/tests/incremental.rs | |||
diff --git a/crates/ra_hir/src/nameres/crate_def_map/tests/macros.rs b/crates/ra_hir/src/nameres/tests/macros.rs index 8781b026b..8781b026b 100644 --- a/crates/ra_hir/src/nameres/crate_def_map/tests/macros.rs +++ b/crates/ra_hir/src/nameres/tests/macros.rs | |||