aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/nameres
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/nameres')
-rw-r--r--crates/ra_hir/src/nameres/collector.rs837
-rw-r--r--crates/ra_hir/src/nameres/per_ns.rs80
-rw-r--r--crates/ra_hir/src/nameres/tests.rs578
-rw-r--r--crates/ra_hir/src/nameres/tests/globs.rs118
-rw-r--r--crates/ra_hir/src/nameres/tests/incremental.rs141
-rw-r--r--crates/ra_hir/src/nameres/tests/macros.rs635
-rw-r--r--crates/ra_hir/src/nameres/tests/mod_resolution.rs759
-rw-r--r--crates/ra_hir/src/nameres/tests/primitives.rs24
8 files changed, 0 insertions, 3172 deletions
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
deleted file mode 100644
index ee0a4c99f..000000000
--- a/crates/ra_hir/src/nameres/collector.rs
+++ /dev/null
@@ -1,837 +0,0 @@
1//! FIXME: write short doc here
2
3use hir_def::{
4 attr::Attr,
5 nameres::{mod_resolution::ModDir, raw},
6};
7use hir_expand::name;
8use ra_cfg::CfgOptions;
9use ra_db::FileId;
10use ra_syntax::{ast, SmolStr};
11use rustc_hash::FxHashMap;
12use test_utils::tested_by;
13
14use crate::{
15 db::DefDatabase,
16 ids::{AstItemDef, LocationCtx, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind},
17 nameres::{
18 diagnostics::DefDiagnostic, Crate, CrateDefMap, CrateModuleId, ModuleData, ModuleDef,
19 PerNs, ReachedFixedPoint, Resolution, ResolveMode,
20 },
21 Adt, AstId, Const, Enum, Function, HirFileId, MacroDef, Module, Name, Path, PathKind, Static,
22 Struct, Trait, TypeAlias, Union,
23};
24
25pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
26 // populate external prelude
27 for dep in def_map.krate.dependencies(db) {
28 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.krate);
29 if let Some(module) = dep.krate.root_module(db) {
30 def_map.extern_prelude.insert(dep.name.clone(), module.into());
31 }
32 // look for the prelude
33 if def_map.prelude.is_none() {
34 let map = db.crate_def_map(dep.krate);
35 if map.prelude.is_some() {
36 def_map.prelude = map.prelude;
37 }
38 }
39 }
40
41 let crate_graph = db.crate_graph();
42 let cfg_options = crate_graph.cfg_options(def_map.krate().crate_id());
43
44 let mut collector = DefCollector {
45 db,
46 def_map,
47 glob_imports: FxHashMap::default(),
48 unresolved_imports: Vec::new(),
49 unexpanded_macros: Vec::new(),
50 mod_dirs: FxHashMap::default(),
51 macro_stack_monitor: MacroStackMonitor::default(),
52 cfg_options,
53 };
54 collector.collect();
55 collector.finish()
56}
57
58#[derive(Default)]
59struct MacroStackMonitor {
60 counts: FxHashMap<MacroDefId, u32>,
61
62 /// Mainly use for test
63 validator: Option<Box<dyn Fn(u32) -> bool>>,
64}
65
66impl MacroStackMonitor {
67 fn increase(&mut self, macro_def_id: MacroDefId) {
68 *self.counts.entry(macro_def_id).or_default() += 1;
69 }
70
71 fn decrease(&mut self, macro_def_id: MacroDefId) {
72 *self.counts.entry(macro_def_id).or_default() -= 1;
73 }
74
75 fn is_poison(&self, macro_def_id: MacroDefId) -> bool {
76 let cur = *self.counts.get(&macro_def_id).unwrap_or(&0);
77
78 if let Some(validator) = &self.validator {
79 validator(cur)
80 } else {
81 cur > 100
82 }
83 }
84}
85
86/// Walks the tree of module recursively
87struct DefCollector<'a, DB> {
88 db: &'a DB,
89 def_map: CrateDefMap,
90 glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>,
91 unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>,
92 unexpanded_macros: Vec<(CrateModuleId, AstId<ast::MacroCall>, Path)>,
93 mod_dirs: FxHashMap<CrateModuleId, ModDir>,
94
95 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly
96 /// To prevent stack overflow, we add a deep counter here for prevent that.
97 macro_stack_monitor: MacroStackMonitor,
98
99 cfg_options: &'a CfgOptions,
100}
101
102impl<DB> DefCollector<'_, DB>
103where
104 DB: DefDatabase,
105{
106 fn collect(&mut self) {
107 let crate_graph = self.db.crate_graph();
108 let file_id = crate_graph.crate_root(self.def_map.krate.crate_id());
109 let raw_items = self.db.raw_items(file_id.into());
110 let module_id = self.def_map.root;
111 self.def_map.modules[module_id].definition = Some(file_id);
112 ModCollector {
113 def_collector: &mut *self,
114 module_id,
115 file_id: file_id.into(),
116 raw_items: &raw_items,
117 mod_dir: ModDir::root(),
118 }
119 .collect(raw_items.items());
120
121 // main name resolution fixed-point loop.
122 let mut i = 0;
123 loop {
124 self.db.check_canceled();
125 match (self.resolve_imports(), self.resolve_macros()) {
126 (ReachedFixedPoint::Yes, ReachedFixedPoint::Yes) => break,
127 _ => i += 1,
128 }
129 if i == 1000 {
130 log::error!("name resolution is stuck");
131 break;
132 }
133 }
134
135 let unresolved_imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
136 // show unresolved imports in completion, etc
137 for (module_id, import, import_data) in unresolved_imports {
138 self.record_resolved_import(module_id, PerNs::none(), import, &import_data)
139 }
140 }
141
142 /// Define a macro with `macro_rules`.
143 ///
144 /// It will define the macro in legacy textual scope, and if it has `#[macro_export]`,
145 /// then it is also defined in the root module scope.
146 /// You can `use` or invoke it by `crate::macro_name` anywhere, before or after the definition.
147 ///
148 /// It is surprising that the macro will never be in the current module scope.
149 /// These code fails with "unresolved import/macro",
150 /// ```rust,compile_fail
151 /// mod m { macro_rules! foo { () => {} } }
152 /// use m::foo as bar;
153 /// ```
154 ///
155 /// ```rust,compile_fail
156 /// macro_rules! foo { () => {} }
157 /// self::foo!();
158 /// crate::foo!();
159 /// ```
160 ///
161 /// Well, this code compiles, bacause the plain path `foo` in `use` is searched
162 /// in the legacy textual scope only.
163 /// ```rust
164 /// macro_rules! foo { () => {} }
165 /// use foo as bar;
166 /// ```
167 fn define_macro(
168 &mut self,
169 module_id: CrateModuleId,
170 name: Name,
171 macro_: MacroDef,
172 export: bool,
173 ) {
174 // Textual scoping
175 self.define_legacy_macro(module_id, name.clone(), macro_);
176
177 // Module scoping
178 // In Rust, `#[macro_export]` macros are unconditionally visible at the
179 // crate root, even if the parent modules is **not** visible.
180 if export {
181 self.update(self.def_map.root, None, &[(name, Resolution::from_macro(macro_))]);
182 }
183 }
184
185 /// Define a legacy textual scoped macro in module
186 ///
187 /// We use a map `legacy_macros` to store all legacy textual scoped macros visable per module.
188 /// It will clone all macros from parent legacy scope, whose definition is prior to
189 /// the definition of current module.
190 /// And also, `macro_use` on a module will import all legacy macros visable inside to
191 /// current legacy scope, with possible shadowing.
192 fn define_legacy_macro(&mut self, module_id: CrateModuleId, name: Name, macro_: MacroDef) {
193 // Always shadowing
194 self.def_map.modules[module_id].scope.legacy_macros.insert(name, macro_);
195 }
196
197 /// Import macros from `#[macro_use] extern crate`.
198 fn import_macros_from_extern_crate(
199 &mut self,
200 current_module_id: CrateModuleId,
201 import: &raw::ImportData,
202 ) {
203 log::debug!(
204 "importing macros from extern crate: {:?} ({:?})",
205 import,
206 self.def_map.edition,
207 );
208
209 let res = self.def_map.resolve_name_in_extern_prelude(
210 &import
211 .path
212 .as_ident()
213 .expect("extern crate should have been desugared to one-element path"),
214 );
215
216 if let Some(ModuleDef::Module(m)) = res.take_types() {
217 tested_by!(macro_rules_from_other_crates_are_visible_with_macro_use);
218 self.import_all_macros_exported(current_module_id, m.krate());
219 }
220 }
221
222 /// Import all exported macros from another crate
223 ///
224 /// Exported macros are just all macros in the root module scope.
225 /// Note that it contains not only all `#[macro_export]` macros, but also all aliases
226 /// created by `use` in the root module, ignoring the visibility of `use`.
227 fn import_all_macros_exported(&mut self, current_module_id: CrateModuleId, krate: Crate) {
228 let def_map = self.db.crate_def_map(krate);
229 for (name, def) in def_map[def_map.root].scope.macros() {
230 // `macro_use` only bring things into legacy scope.
231 self.define_legacy_macro(current_module_id, name.clone(), def);
232 }
233 }
234
235 fn resolve_imports(&mut self) -> ReachedFixedPoint {
236 let mut imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
237 let mut resolved = Vec::new();
238 imports.retain(|(module_id, import, import_data)| {
239 let (def, fp) = self.resolve_import(*module_id, import_data);
240 if fp == ReachedFixedPoint::Yes {
241 resolved.push((*module_id, def, *import, import_data.clone()))
242 }
243 fp == ReachedFixedPoint::No
244 });
245 self.unresolved_imports = imports;
246 // Resolves imports, filling-in module scopes
247 let result =
248 if resolved.is_empty() { ReachedFixedPoint::Yes } else { ReachedFixedPoint::No };
249 for (module_id, def, import, import_data) in resolved {
250 self.record_resolved_import(module_id, def, import, &import_data)
251 }
252 result
253 }
254
255 fn resolve_import(
256 &self,
257 module_id: CrateModuleId,
258 import: &raw::ImportData,
259 ) -> (PerNs, ReachedFixedPoint) {
260 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
261 if import.is_extern_crate {
262 let res = self.def_map.resolve_name_in_extern_prelude(
263 &import
264 .path
265 .as_ident()
266 .expect("extern crate should have been desugared to one-element path"),
267 );
268 (res, ReachedFixedPoint::Yes)
269 } else {
270 let res = self.def_map.resolve_path_fp_with_macro(
271 self.db,
272 ResolveMode::Import,
273 module_id,
274 &import.path,
275 );
276
277 (res.resolved_def, res.reached_fixedpoint)
278 }
279 }
280
281 fn record_resolved_import(
282 &mut self,
283 module_id: CrateModuleId,
284 def: PerNs,
285 import_id: raw::ImportId,
286 import: &raw::ImportData,
287 ) {
288 if import.is_glob {
289 log::debug!("glob import: {:?}", import);
290 match def.take_types() {
291 Some(ModuleDef::Module(m)) => {
292 if import.is_prelude {
293 tested_by!(std_prelude);
294 self.def_map.prelude = Some(m);
295 } else if m.krate() != self.def_map.krate {
296 tested_by!(glob_across_crates);
297 // glob import from other crate => we can just import everything once
298 let item_map = self.db.crate_def_map(m.krate());
299 let scope = &item_map[m.id.module_id].scope;
300
301 // Module scoped macros is included
302 let items = scope
303 .items
304 .iter()
305 .map(|(name, res)| (name.clone(), res.clone()))
306 .collect::<Vec<_>>();
307
308 self.update(module_id, Some(import_id), &items);
309 } else {
310 // glob import from same crate => we do an initial
311 // import, and then need to propagate any further
312 // additions
313 let scope = &self.def_map[m.id.module_id].scope;
314
315 // Module scoped macros is included
316 let items = scope
317 .items
318 .iter()
319 .map(|(name, res)| (name.clone(), res.clone()))
320 .collect::<Vec<_>>();
321
322 self.update(module_id, Some(import_id), &items);
323 // record the glob import in case we add further items
324 self.glob_imports
325 .entry(m.id.module_id)
326 .or_default()
327 .push((module_id, import_id));
328 }
329 }
330 Some(ModuleDef::Adt(Adt::Enum(e))) => {
331 tested_by!(glob_enum);
332 // glob import from enum => just import all the variants
333 let variants = e.variants(self.db);
334 let resolutions = variants
335 .into_iter()
336 .filter_map(|variant| {
337 let res = Resolution {
338 def: PerNs::both(variant.into(), variant.into()),
339 import: Some(import_id),
340 };
341 let name = variant.name(self.db)?;
342 Some((name, res))
343 })
344 .collect::<Vec<_>>();
345 self.update(module_id, Some(import_id), &resolutions);
346 }
347 Some(d) => {
348 log::debug!("glob import {:?} from non-module/enum {:?}", import, d);
349 }
350 None => {
351 log::debug!("glob import {:?} didn't resolve as type", import);
352 }
353 }
354 } else {
355 match import.path.segments.last() {
356 Some(last_segment) => {
357 let name = import.alias.clone().unwrap_or_else(|| last_segment.name.clone());
358 log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
359
360 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
361 if import.is_extern_crate && module_id == self.def_map.root {
362 if let Some(def) = def.take_types() {
363 self.def_map.extern_prelude.insert(name.clone(), def);
364 }
365 }
366
367 let resolution = Resolution { def, import: Some(import_id) };
368 self.update(module_id, Some(import_id), &[(name, resolution)]);
369 }
370 None => tested_by!(bogus_paths),
371 }
372 }
373 }
374
375 fn update(
376 &mut self,
377 module_id: CrateModuleId,
378 import: Option<raw::ImportId>,
379 resolutions: &[(Name, Resolution)],
380 ) {
381 self.update_recursive(module_id, import, resolutions, 0)
382 }
383
384 fn update_recursive(
385 &mut self,
386 module_id: CrateModuleId,
387 import: Option<raw::ImportId>,
388 resolutions: &[(Name, Resolution)],
389 depth: usize,
390 ) {
391 if depth > 100 {
392 // prevent stack overflows (but this shouldn't be possible)
393 panic!("infinite recursion in glob imports!");
394 }
395 let module_items = &mut self.def_map.modules[module_id].scope;
396 let mut changed = false;
397 for (name, res) in resolutions {
398 let existing = module_items.items.entry(name.clone()).or_default();
399
400 if existing.def.types.is_none() && res.def.types.is_some() {
401 existing.def.types = res.def.types;
402 existing.import = import.or(res.import);
403 changed = true;
404 }
405 if existing.def.values.is_none() && res.def.values.is_some() {
406 existing.def.values = res.def.values;
407 existing.import = import.or(res.import);
408 changed = true;
409 }
410 if existing.def.macros.is_none() && res.def.macros.is_some() {
411 existing.def.macros = res.def.macros;
412 existing.import = import.or(res.import);
413 changed = true;
414 }
415
416 if existing.def.is_none()
417 && res.def.is_none()
418 && existing.import.is_none()
419 && res.import.is_some()
420 {
421 existing.import = res.import;
422 }
423 }
424
425 if !changed {
426 return;
427 }
428 let glob_imports = self
429 .glob_imports
430 .get(&module_id)
431 .into_iter()
432 .flat_map(|v| v.iter())
433 .cloned()
434 .collect::<Vec<_>>();
435 for (glob_importing_module, glob_import) in glob_imports {
436 // We pass the glob import so that the tracked import in those modules is that glob import
437 self.update_recursive(glob_importing_module, Some(glob_import), resolutions, depth + 1);
438 }
439 }
440
441 fn resolve_macros(&mut self) -> ReachedFixedPoint {
442 let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new());
443 let mut resolved = Vec::new();
444 let mut res = ReachedFixedPoint::Yes;
445 macros.retain(|(module_id, ast_id, path)| {
446 let resolved_res = self.def_map.resolve_path_fp_with_macro(
447 self.db,
448 ResolveMode::Other,
449 *module_id,
450 path,
451 );
452
453 if let Some(def) = resolved_res.resolved_def.get_macros() {
454 let call_id = self.db.intern_macro(MacroCallLoc { def: def.id, ast_id: *ast_id });
455 resolved.push((*module_id, call_id, def.id));
456 res = ReachedFixedPoint::No;
457 return false;
458 }
459
460 true
461 });
462
463 self.unexpanded_macros = macros;
464
465 for (module_id, macro_call_id, macro_def_id) in resolved {
466 self.collect_macro_expansion(module_id, macro_call_id, macro_def_id);
467 }
468
469 res
470 }
471
472 fn collect_macro_expansion(
473 &mut self,
474 module_id: CrateModuleId,
475 macro_call_id: MacroCallId,
476 macro_def_id: MacroDefId,
477 ) {
478 if self.def_map.poison_macros.contains(&macro_def_id) {
479 return;
480 }
481
482 self.macro_stack_monitor.increase(macro_def_id);
483
484 if !self.macro_stack_monitor.is_poison(macro_def_id) {
485 let file_id: HirFileId = macro_call_id.as_file(MacroFileKind::Items);
486 let raw_items = self.db.raw_items(file_id);
487 let mod_dir = self.mod_dirs[&module_id].clone();
488 ModCollector {
489 def_collector: &mut *self,
490 file_id,
491 module_id,
492 raw_items: &raw_items,
493 mod_dir,
494 }
495 .collect(raw_items.items());
496 } else {
497 log::error!("Too deep macro expansion: {:?}", macro_call_id);
498 self.def_map.poison_macros.insert(macro_def_id);
499 }
500
501 self.macro_stack_monitor.decrease(macro_def_id);
502 }
503
504 fn finish(self) -> CrateDefMap {
505 self.def_map
506 }
507}
508
509/// Walks a single module, populating defs, imports and macros
510struct ModCollector<'a, D> {
511 def_collector: D,
512 module_id: CrateModuleId,
513 file_id: HirFileId,
514 raw_items: &'a raw::RawItems,
515 mod_dir: ModDir,
516}
517
518impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>>
519where
520 DB: DefDatabase,
521{
522 fn collect(&mut self, items: &[raw::RawItem]) {
523 // Note: don't assert that inserted value is fresh: it's simply not true
524 // for macros.
525 self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
526
527 // Prelude module is always considered to be `#[macro_use]`.
528 if let Some(prelude_module) = self.def_collector.def_map.prelude {
529 if prelude_module.krate() != self.def_collector.def_map.krate {
530 tested_by!(prelude_is_macro_use);
531 self.def_collector
532 .import_all_macros_exported(self.module_id, prelude_module.krate());
533 }
534 }
535
536 // This should be processed eagerly instead of deferred to resolving.
537 // `#[macro_use] extern crate` is hoisted to imports macros before collecting
538 // any other items.
539 for item in items {
540 if self.is_cfg_enabled(item.attrs()) {
541 if let raw::RawItemKind::Import(import_id) = item.kind {
542 let import = self.raw_items[import_id].clone();
543 if import.is_extern_crate && import.is_macro_use {
544 self.def_collector.import_macros_from_extern_crate(self.module_id, &import);
545 }
546 }
547 }
548 }
549
550 for item in items {
551 if self.is_cfg_enabled(item.attrs()) {
552 match item.kind {
553 raw::RawItemKind::Module(m) => {
554 self.collect_module(&self.raw_items[m], item.attrs())
555 }
556 raw::RawItemKind::Import(import_id) => self
557 .def_collector
558 .unresolved_imports
559 .push((self.module_id, import_id, self.raw_items[import_id].clone())),
560 raw::RawItemKind::Def(def) => self.define_def(&self.raw_items[def]),
561 raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]),
562 }
563 }
564 }
565 }
566
567 fn collect_module(&mut self, module: &raw::ModuleData, attrs: &[Attr]) {
568 let path_attr = self.path_attr(attrs);
569 let is_macro_use = self.is_macro_use(attrs);
570 match module {
571 // inline module, just recurse
572 raw::ModuleData::Definition { name, items, ast_id } => {
573 let module_id =
574 self.push_child_module(name.clone(), AstId::new(self.file_id, *ast_id), None);
575
576 ModCollector {
577 def_collector: &mut *self.def_collector,
578 module_id,
579 file_id: self.file_id,
580 raw_items: self.raw_items,
581 mod_dir: self.mod_dir.descend_into_definition(name, path_attr),
582 }
583 .collect(&*items);
584 if is_macro_use {
585 self.import_all_legacy_macros(module_id);
586 }
587 }
588 // out of line module, resolve, parse and recurse
589 raw::ModuleData::Declaration { name, ast_id } => {
590 let ast_id = AstId::new(self.file_id, *ast_id);
591 match self.mod_dir.resolve_declaration(
592 self.def_collector.db,
593 self.file_id,
594 name,
595 path_attr,
596 ) {
597 Ok((file_id, mod_dir)) => {
598 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id));
599 let raw_items = self.def_collector.db.raw_items(file_id.into());
600 ModCollector {
601 def_collector: &mut *self.def_collector,
602 module_id,
603 file_id: file_id.into(),
604 raw_items: &raw_items,
605 mod_dir,
606 }
607 .collect(raw_items.items());
608 if is_macro_use {
609 self.import_all_legacy_macros(module_id);
610 }
611 }
612 Err(candidate) => self.def_collector.def_map.diagnostics.push(
613 DefDiagnostic::UnresolvedModule {
614 module: self.module_id,
615 declaration: ast_id,
616 candidate,
617 },
618 ),
619 };
620 }
621 }
622 }
623
624 fn push_child_module(
625 &mut self,
626 name: Name,
627 declaration: AstId<ast::Module>,
628 definition: Option<FileId>,
629 ) -> CrateModuleId {
630 let modules = &mut self.def_collector.def_map.modules;
631 let res = modules.alloc(ModuleData::default());
632 modules[res].parent = Some(self.module_id);
633 modules[res].declaration = Some(declaration);
634 modules[res].definition = definition;
635 modules[res].scope.legacy_macros = modules[self.module_id].scope.legacy_macros.clone();
636 modules[self.module_id].children.insert(name.clone(), res);
637 let resolution = Resolution {
638 def: PerNs::types(Module::new(self.def_collector.def_map.krate, res).into()),
639 import: None,
640 };
641 self.def_collector.update(self.module_id, None, &[(name, resolution)]);
642 res
643 }
644
645 fn define_def(&mut self, def: &raw::DefData) {
646 let module = Module::new(self.def_collector.def_map.krate, self.module_id);
647 let ctx = LocationCtx::new(self.def_collector.db, module.id, self.file_id);
648
649 macro_rules! def {
650 ($kind:ident, $ast_id:ident) => {
651 $kind { id: AstItemDef::from_ast_id(ctx, $ast_id) }.into()
652 };
653 }
654 let name = def.name.clone();
655 let def: PerNs = match def.kind {
656 raw::DefKind::Function(ast_id) => PerNs::values(def!(Function, ast_id)),
657 raw::DefKind::Struct(ast_id) => {
658 let s = def!(Struct, ast_id);
659 PerNs::both(s, s)
660 }
661 raw::DefKind::Union(ast_id) => {
662 let s = def!(Union, ast_id);
663 PerNs::both(s, s)
664 }
665 raw::DefKind::Enum(ast_id) => PerNs::types(def!(Enum, ast_id)),
666 raw::DefKind::Const(ast_id) => PerNs::values(def!(Const, ast_id)),
667 raw::DefKind::Static(ast_id) => PerNs::values(def!(Static, ast_id)),
668 raw::DefKind::Trait(ast_id) => PerNs::types(def!(Trait, ast_id)),
669 raw::DefKind::TypeAlias(ast_id) => PerNs::types(def!(TypeAlias, ast_id)),
670 };
671 let resolution = Resolution { def, import: None };
672 self.def_collector.update(self.module_id, None, &[(name, resolution)])
673 }
674
675 fn collect_macro(&mut self, mac: &raw::MacroData) {
676 let ast_id = AstId::new(self.file_id, mac.ast_id);
677
678 // Case 1: macro rules, define a macro in crate-global mutable scope
679 if is_macro_rules(&mac.path) {
680 if let Some(name) = &mac.name {
681 let macro_id =
682 MacroDefId { ast_id, krate: self.def_collector.def_map.krate.crate_id };
683 let macro_ = MacroDef { id: macro_id };
684 self.def_collector.define_macro(self.module_id, name.clone(), macro_, mac.export);
685 }
686 return;
687 }
688
689 // Case 2: try to resolve in legacy scope and expand macro_rules, triggering
690 // recursive item collection.
691 if let Some(macro_def) = mac.path.as_ident().and_then(|name| {
692 self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name)
693 }) {
694 let def = macro_def.id;
695 let macro_call_id = self.def_collector.db.intern_macro(MacroCallLoc { def, ast_id });
696
697 self.def_collector.collect_macro_expansion(self.module_id, macro_call_id, def);
698 return;
699 }
700
701 // Case 3: resolve in module scope, expand during name resolution.
702 // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only.
703 let mut path = mac.path.clone();
704 if path.is_ident() {
705 path.kind = PathKind::Self_;
706 }
707 self.def_collector.unexpanded_macros.push((self.module_id, ast_id, path));
708 }
709
710 fn import_all_legacy_macros(&mut self, module_id: CrateModuleId) {
711 let macros = self.def_collector.def_map[module_id].scope.legacy_macros.clone();
712 for (name, macro_) in macros {
713 self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
714 }
715 }
716
717 fn is_cfg_enabled(&self, attrs: &[Attr]) -> bool {
718 attrs.iter().all(|attr| attr.is_cfg_enabled(&self.def_collector.cfg_options) != Some(false))
719 }
720
721 fn path_attr<'a>(&self, attrs: &'a [Attr]) -> Option<&'a SmolStr> {
722 attrs.iter().find_map(|attr| attr.as_path())
723 }
724
725 fn is_macro_use<'a>(&self, attrs: &'a [Attr]) -> bool {
726 attrs.iter().any(|attr| attr.is_simple_atom("macro_use"))
727 }
728}
729
730fn is_macro_rules(path: &Path) -> bool {
731 path.as_ident() == Some(&name::MACRO_RULES)
732}
733
734#[cfg(test)]
735mod tests {
736 use ra_db::SourceDatabase;
737
738 use super::*;
739 use crate::{db::DefDatabase, mock::MockDatabase, Crate};
740 use ra_arena::Arena;
741 use rustc_hash::FxHashSet;
742
743 fn do_collect_defs(
744 db: &impl DefDatabase,
745 def_map: CrateDefMap,
746 monitor: MacroStackMonitor,
747 ) -> CrateDefMap {
748 let mut collector = DefCollector {
749 db,
750 def_map,
751 glob_imports: FxHashMap::default(),
752 unresolved_imports: Vec::new(),
753 unexpanded_macros: Vec::new(),
754 mod_dirs: FxHashMap::default(),
755 macro_stack_monitor: monitor,
756 cfg_options: &CfgOptions::default(),
757 };
758 collector.collect();
759 collector.finish()
760 }
761
762 fn do_limited_resolve(code: &str, limit: u32, poison_limit: u32) -> CrateDefMap {
763 let (db, _source_root, _) = MockDatabase::with_single_file(&code);
764 let crate_id = db.crate_graph().iter().next().unwrap();
765 let krate = Crate { crate_id };
766
767 let def_map = {
768 let edition = krate.edition(&db);
769 let mut modules: Arena<CrateModuleId, ModuleData> = Arena::default();
770 let root = modules.alloc(ModuleData::default());
771 CrateDefMap {
772 krate,
773 edition,
774 extern_prelude: FxHashMap::default(),
775 prelude: None,
776 root,
777 modules,
778 poison_macros: FxHashSet::default(),
779 diagnostics: Vec::new(),
780 }
781 };
782
783 let mut monitor = MacroStackMonitor::default();
784 monitor.validator = Some(Box::new(move |count| {
785 assert!(count < limit);
786 count >= poison_limit
787 }));
788
789 do_collect_defs(&db, def_map, monitor)
790 }
791
792 #[test]
793 fn test_macro_expand_limit_width() {
794 do_limited_resolve(
795 r#"
796 macro_rules! foo {
797 ($($ty:ty)*) => { foo!($($ty)*, $($ty)*); }
798 }
799foo!(KABOOM);
800 "#,
801 16,
802 1000,
803 );
804 }
805
806 #[test]
807 fn test_macro_expand_poisoned() {
808 let def = do_limited_resolve(
809 r#"
810 macro_rules! foo {
811 ($ty:ty) => { foo!($ty); }
812 }
813foo!(KABOOM);
814 "#,
815 100,
816 16,
817 );
818
819 assert_eq!(def.poison_macros.len(), 1);
820 }
821
822 #[test]
823 fn test_macro_expand_normal() {
824 let def = do_limited_resolve(
825 r#"
826 macro_rules! foo {
827 ($ident:ident) => { struct $ident {} }
828 }
829foo!(Bar);
830 "#,
831 16,
832 16,
833 );
834
835 assert_eq!(def.poison_macros.len(), 0);
836 }
837}
diff --git a/crates/ra_hir/src/nameres/per_ns.rs b/crates/ra_hir/src/nameres/per_ns.rs
deleted file mode 100644
index 0da6789de..000000000
--- a/crates/ra_hir/src/nameres/per_ns.rs
+++ /dev/null
@@ -1,80 +0,0 @@
1//! FIXME: write short doc here
2
3use crate::{MacroDef, ModuleDef};
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
6pub enum Namespace {
7 Types,
8 Values,
9 // Note that only type inference uses this enum, and it doesn't care about macros.
10 // Macro,
11}
12
13#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
14pub struct PerNs {
15 pub types: Option<ModuleDef>,
16 pub values: Option<ModuleDef>,
17 /// Since macros has different type, many methods simply ignore it.
18 /// We can only use special method like `get_macros` to access it.
19 pub macros: Option<MacroDef>,
20}
21
22impl Default for PerNs {
23 fn default() -> Self {
24 PerNs { types: None, values: None, macros: None }
25 }
26}
27
28impl PerNs {
29 pub fn none() -> PerNs {
30 PerNs { types: None, values: None, macros: None }
31 }
32
33 pub fn values(t: ModuleDef) -> PerNs {
34 PerNs { types: None, values: Some(t), macros: None }
35 }
36
37 pub fn types(t: ModuleDef) -> PerNs {
38 PerNs { types: Some(t), values: None, macros: None }
39 }
40
41 pub fn both(types: ModuleDef, values: ModuleDef) -> PerNs {
42 PerNs { types: Some(types), values: Some(values), macros: None }
43 }
44
45 pub fn macros(macro_: MacroDef) -> PerNs {
46 PerNs { types: None, values: None, macros: Some(macro_) }
47 }
48
49 pub fn is_none(&self) -> bool {
50 self.types.is_none() && self.values.is_none() && self.macros.is_none()
51 }
52
53 pub fn is_all(&self) -> bool {
54 self.types.is_some() && self.values.is_some() && self.macros.is_some()
55 }
56
57 pub fn take_types(self) -> Option<ModuleDef> {
58 self.types
59 }
60
61 pub fn take_values(self) -> Option<ModuleDef> {
62 self.values
63 }
64
65 pub fn get_macros(&self) -> Option<MacroDef> {
66 self.macros
67 }
68
69 pub fn only_macros(&self) -> PerNs {
70 PerNs { types: None, values: None, macros: self.macros }
71 }
72
73 pub fn or(self, other: PerNs) -> PerNs {
74 PerNs {
75 types: self.types.or(other.types),
76 values: self.values.or(other.values),
77 macros: self.macros.or(other.macros),
78 }
79 }
80}
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs
deleted file mode 100644
index 8c6b40aaf..000000000
--- a/crates/ra_hir/src/nameres/tests.rs
+++ /dev/null
@@ -1,578 +0,0 @@
1mod macros;
2mod globs;
3mod incremental;
4mod primitives;
5mod mod_resolution;
6
7use std::sync::Arc;
8
9use insta::assert_snapshot;
10use ra_db::SourceDatabase;
11use test_utils::covers;
12
13use crate::{
14 mock::{CrateGraphFixture, MockDatabase},
15 Crate,
16};
17
18use super::*;
19
20fn compute_crate_def_map(fixture: &str, graph: Option<CrateGraphFixture>) -> Arc<CrateDefMap> {
21 let mut db = MockDatabase::with_files(fixture);
22 if let Some(graph) = graph {
23 db.set_crate_graph_from_fixture(graph);
24 }
25 let crate_id = db.crate_graph().iter().next().unwrap();
26 let krate = Crate { crate_id };
27 db.crate_def_map(krate)
28}
29
30fn render_crate_def_map(map: &CrateDefMap) -> String {
31 let mut buf = String::new();
32 go(&mut buf, map, "\ncrate", map.root);
33 return buf.trim().to_string();
34
35 fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: CrateModuleId) {
36 *buf += path;
37 *buf += "\n";
38
39 let mut entries = map.modules[module]
40 .scope
41 .items
42 .iter()
43 .map(|(name, res)| (name, res.def))
44 .collect::<Vec<_>>();
45 entries.sort_by_key(|(name, _)| *name);
46
47 for (name, res) in entries {
48 *buf += &format!("{}:", name);
49
50 if res.types.is_some() {
51 *buf += " t";
52 }
53 if res.values.is_some() {
54 *buf += " v";
55 }
56 if res.macros.is_some() {
57 *buf += " m";
58 }
59 if res.is_none() {
60 *buf += " _";
61 }
62
63 *buf += "\n";
64 }
65
66 for (name, child) in map.modules[module].children.iter() {
67 let path = path.to_string() + &format!("::{}", name);
68 go(buf, map, &path, *child);
69 }
70 }
71}
72
73fn def_map(fixtute: &str) -> String {
74 let dm = compute_crate_def_map(fixtute, None);
75 render_crate_def_map(&dm)
76}
77
78fn def_map_with_crate_graph(fixture: &str, graph: CrateGraphFixture) -> String {
79 let dm = compute_crate_def_map(fixture, Some(graph));
80 render_crate_def_map(&dm)
81}
82
83#[test]
84fn crate_def_map_smoke_test() {
85 let map = def_map(
86 "
87 //- /lib.rs
88 mod foo;
89 struct S;
90 use crate::foo::bar::E;
91 use self::E::V;
92
93 //- /foo/mod.rs
94 pub mod bar;
95 fn f() {}
96
97 //- /foo/bar.rs
98 pub struct Baz;
99 enum E { V }
100 ",
101 );
102 assert_snapshot!(map, @r###"
103 ⋮crate
104 ⋮E: t
105 ⋮S: t v
106 ⋮V: t v
107 ⋮foo: t
108
109 ⋮crate::foo
110 ⋮bar: t
111 ⋮f: v
112
113 ⋮crate::foo::bar
114 ⋮Baz: t v
115 ⋮E: t
116 "###)
117}
118
119#[test]
120fn bogus_paths() {
121 covers!(bogus_paths);
122 let map = def_map(
123 "
124 //- /lib.rs
125 mod foo;
126 struct S;
127 use self;
128
129 //- /foo/mod.rs
130 use super;
131 use crate;
132
133 ",
134 );
135 assert_snapshot!(map, @r###"
136 ⋮crate
137 ⋮S: t v
138 ⋮foo: t
139
140 ⋮crate::foo
141 "###
142 )
143}
144
145#[test]
146fn use_as() {
147 let map = def_map(
148 "
149 //- /lib.rs
150 mod foo;
151
152 use crate::foo::Baz as Foo;
153
154 //- /foo/mod.rs
155 pub struct Baz;
156 ",
157 );
158 assert_snapshot!(map,
159 @r###"
160 ⋮crate
161 ⋮Foo: t v
162 ⋮foo: t
163
164 ⋮crate::foo
165 ⋮Baz: t v
166 "###
167 );
168}
169
170#[test]
171fn use_trees() {
172 let map = def_map(
173 "
174 //- /lib.rs
175 mod foo;
176
177 use crate::foo::bar::{Baz, Quux};
178
179 //- /foo/mod.rs
180 pub mod bar;
181
182 //- /foo/bar.rs
183 pub struct Baz;
184 pub enum Quux {};
185 ",
186 );
187 assert_snapshot!(map, @r###"
188 ⋮crate
189 ⋮Baz: t v
190 ⋮Quux: t
191 ⋮foo: t
192
193 ⋮crate::foo
194 ⋮bar: t
195
196 ⋮crate::foo::bar
197 ⋮Baz: t v
198 ⋮Quux: t
199 "###);
200}
201
202#[test]
203fn re_exports() {
204 let map = def_map(
205 "
206 //- /lib.rs
207 mod foo;
208
209 use self::foo::Baz;
210
211 //- /foo/mod.rs
212 pub mod bar;
213
214 pub use self::bar::Baz;
215
216 //- /foo/bar.rs
217 pub struct Baz;
218 ",
219 );
220 assert_snapshot!(map, @r###"
221 ⋮crate
222 ⋮Baz: t v
223 ⋮foo: t
224
225 ⋮crate::foo
226 ⋮Baz: t v
227 ⋮bar: t
228
229 ⋮crate::foo::bar
230 ⋮Baz: t v
231 "###);
232}
233
234#[test]
235fn std_prelude() {
236 covers!(std_prelude);
237 let map = def_map_with_crate_graph(
238 "
239 //- /main.rs
240 use Foo::*;
241
242 //- /lib.rs
243 mod prelude;
244 #[prelude_import]
245 use prelude::*;
246
247 //- /prelude.rs
248 pub enum Foo { Bar, Baz };
249 ",
250 crate_graph! {
251 "main": ("/main.rs", ["test_crate"]),
252 "test_crate": ("/lib.rs", []),
253 },
254 );
255 assert_snapshot!(map, @r###"
256 ⋮crate
257 ⋮Bar: t v
258 ⋮Baz: t v
259 "###);
260}
261
262#[test]
263fn can_import_enum_variant() {
264 covers!(can_import_enum_variant);
265 let map = def_map(
266 "
267 //- /lib.rs
268 enum E { V }
269 use self::E::V;
270 ",
271 );
272 assert_snapshot!(map, @r###"
273 ⋮crate
274 ⋮E: t
275 ⋮V: t v
276 "###
277 );
278}
279
280#[test]
281fn edition_2015_imports() {
282 let map = def_map_with_crate_graph(
283 "
284 //- /main.rs
285 mod foo;
286 mod bar;
287
288 //- /bar.rs
289 struct Bar;
290
291 //- /foo.rs
292 use bar::Bar;
293 use other_crate::FromLib;
294
295 //- /lib.rs
296 struct FromLib;
297 ",
298 crate_graph! {
299 "main": ("/main.rs", "2015", ["other_crate"]),
300 "other_crate": ("/lib.rs", "2018", []),
301 },
302 );
303
304 assert_snapshot!(map, @r###"
305 ⋮crate
306 ⋮bar: t
307 ⋮foo: t
308
309 ⋮crate::bar
310 ⋮Bar: t v
311
312 ⋮crate::foo
313 ⋮Bar: t v
314 ⋮FromLib: t v
315 "###);
316}
317
318#[test]
319fn item_map_using_self() {
320 let map = def_map(
321 "
322 //- /lib.rs
323 mod foo;
324 use crate::foo::bar::Baz::{self};
325 //- /foo/mod.rs
326 pub mod bar;
327 //- /foo/bar.rs
328 pub struct Baz;
329 ",
330 );
331 assert_snapshot!(map, @r###"
332 ⋮crate
333 ⋮Baz: t v
334 ⋮foo: t
335
336 ⋮crate::foo
337 ⋮bar: t
338
339 ⋮crate::foo::bar
340 ⋮Baz: t v
341 "###);
342}
343
344#[test]
345fn item_map_across_crates() {
346 let map = def_map_with_crate_graph(
347 "
348 //- /main.rs
349 use test_crate::Baz;
350
351 //- /lib.rs
352 pub struct Baz;
353 ",
354 crate_graph! {
355 "main": ("/main.rs", ["test_crate"]),
356 "test_crate": ("/lib.rs", []),
357 },
358 );
359
360 assert_snapshot!(map, @r###"
361 ⋮crate
362 ⋮Baz: t v
363 "###);
364}
365
366#[test]
367fn extern_crate_rename() {
368 let map = def_map_with_crate_graph(
369 "
370 //- /main.rs
371 extern crate alloc as alloc_crate;
372
373 mod alloc;
374 mod sync;
375
376 //- /sync.rs
377 use alloc_crate::Arc;
378
379 //- /lib.rs
380 struct Arc;
381 ",
382 crate_graph! {
383 "main": ("/main.rs", ["alloc"]),
384 "alloc": ("/lib.rs", []),
385 },
386 );
387
388 assert_snapshot!(map, @r###"
389 ⋮crate
390 ⋮alloc_crate: t
391 ⋮sync: t
392
393 ⋮crate::sync
394 ⋮Arc: t v
395 "###);
396}
397
398#[test]
399fn extern_crate_rename_2015_edition() {
400 let map = def_map_with_crate_graph(
401 "
402 //- /main.rs
403 extern crate alloc as alloc_crate;
404
405 mod alloc;
406 mod sync;
407
408 //- /sync.rs
409 use alloc_crate::Arc;
410
411 //- /lib.rs
412 struct Arc;
413 ",
414 crate_graph! {
415 "main": ("/main.rs", "2015", ["alloc"]),
416 "alloc": ("/lib.rs", []),
417 },
418 );
419
420 assert_snapshot!(map,
421 @r###"
422 ⋮crate
423 ⋮alloc_crate: t
424 ⋮sync: t
425
426 ⋮crate::sync
427 ⋮Arc: t v
428 "###
429 );
430}
431
432#[test]
433fn import_across_source_roots() {
434 let map = def_map_with_crate_graph(
435 "
436 //- /lib.rs
437 pub mod a {
438 pub mod b {
439 pub struct C;
440 }
441 }
442
443 //- root /main/
444
445 //- /main/main.rs
446 use test_crate::a::b::C;
447 ",
448 crate_graph! {
449 "main": ("/main/main.rs", ["test_crate"]),
450 "test_crate": ("/lib.rs", []),
451 },
452 );
453
454 assert_snapshot!(map, @r###"
455 ⋮crate
456 ⋮C: t v
457 "###);
458}
459
460#[test]
461fn reexport_across_crates() {
462 let map = def_map_with_crate_graph(
463 "
464 //- /main.rs
465 use test_crate::Baz;
466
467 //- /lib.rs
468 pub use foo::Baz;
469
470 mod foo;
471
472 //- /foo.rs
473 pub struct Baz;
474 ",
475 crate_graph! {
476 "main": ("/main.rs", ["test_crate"]),
477 "test_crate": ("/lib.rs", []),
478 },
479 );
480
481 assert_snapshot!(map, @r###"
482 ⋮crate
483 ⋮Baz: t v
484 "###);
485}
486
487#[test]
488fn values_dont_shadow_extern_crates() {
489 let map = def_map_with_crate_graph(
490 "
491 //- /main.rs
492 fn foo() {}
493 use foo::Bar;
494
495 //- /foo/lib.rs
496 pub struct Bar;
497 ",
498 crate_graph! {
499 "main": ("/main.rs", ["foo"]),
500 "foo": ("/foo/lib.rs", []),
501 },
502 );
503
504 assert_snapshot!(map, @r###"
505 ⋮crate
506 ⋮Bar: t v
507 ⋮foo: v
508 "###);
509}
510
511#[test]
512fn cfg_not_test() {
513 let map = def_map_with_crate_graph(
514 r#"
515 //- /main.rs
516 use {Foo, Bar, Baz};
517 //- /lib.rs
518 #[prelude_import]
519 pub use self::prelude::*;
520 mod prelude {
521 #[cfg(test)]
522 pub struct Foo;
523 #[cfg(not(test))]
524 pub struct Bar;
525 #[cfg(all(not(any()), feature = "foo", feature = "bar", opt = "42"))]
526 pub struct Baz;
527 }
528 "#,
529 crate_graph! {
530 "main": ("/main.rs", ["std"]),
531 "std": ("/lib.rs", []),
532 },
533 );
534
535 assert_snapshot!(map, @r###"
536 ⋮crate
537 ⋮Bar: t v
538 ⋮Baz: _
539 ⋮Foo: _
540 "###);
541}
542
543#[test]
544fn cfg_test() {
545 let map = def_map_with_crate_graph(
546 r#"
547 //- /main.rs
548 use {Foo, Bar, Baz};
549 //- /lib.rs
550 #[prelude_import]
551 pub use self::prelude::*;
552 mod prelude {
553 #[cfg(test)]
554 pub struct Foo;
555 #[cfg(not(test))]
556 pub struct Bar;
557 #[cfg(all(not(any()), feature = "foo", feature = "bar", opt = "42"))]
558 pub struct Baz;
559 }
560 "#,
561 crate_graph! {
562 "main": ("/main.rs", ["std"]),
563 "std": ("/lib.rs", [], cfg = {
564 "test",
565 "feature" = "foo",
566 "feature" = "bar",
567 "opt" = "42",
568 }),
569 },
570 );
571
572 assert_snapshot!(map, @r###"
573 ⋮crate
574 ⋮Bar: _
575 ⋮Baz: t v
576 ⋮Foo: t v
577 "###);
578}
diff --git a/crates/ra_hir/src/nameres/tests/globs.rs b/crates/ra_hir/src/nameres/tests/globs.rs
deleted file mode 100644
index 7ac22b47b..000000000
--- a/crates/ra_hir/src/nameres/tests/globs.rs
+++ /dev/null
@@ -1,118 +0,0 @@
1use super::*;
2
3#[test]
4fn glob_1() {
5 let map = def_map(
6 "
7 //- /lib.rs
8 mod foo;
9 use foo::*;
10
11 //- /foo/mod.rs
12 pub mod bar;
13 pub use self::bar::Baz;
14 pub struct Foo;
15
16 //- /foo/bar.rs
17 pub struct Baz;
18 ",
19 );
20 assert_snapshot!(map, @r###"
21 ⋮crate
22 ⋮Baz: t v
23 ⋮Foo: t v
24 ⋮bar: t
25 ⋮foo: t
26
27 ⋮crate::foo
28 ⋮Baz: t v
29 ⋮Foo: t v
30 ⋮bar: t
31
32 ⋮crate::foo::bar
33 ⋮Baz: t v
34 "###
35 );
36}
37
38#[test]
39fn glob_2() {
40 let map = def_map(
41 "
42 //- /lib.rs
43 mod foo;
44 use foo::*;
45
46 //- /foo/mod.rs
47 pub mod bar;
48 pub use self::bar::*;
49 pub struct Foo;
50
51 //- /foo/bar.rs
52 pub struct Baz;
53 pub use super::*;
54 ",
55 );
56 assert_snapshot!(map, @r###"
57 ⋮crate
58 ⋮Baz: t v
59 ⋮Foo: t v
60 ⋮bar: t
61 ⋮foo: t
62
63 ⋮crate::foo
64 ⋮Baz: t v
65 ⋮Foo: t v
66 ⋮bar: t
67
68 ⋮crate::foo::bar
69 ⋮Baz: t v
70 ⋮Foo: t v
71 ⋮bar: t
72 "###
73 );
74}
75
76#[test]
77fn glob_across_crates() {
78 covers!(glob_across_crates);
79 let map = def_map_with_crate_graph(
80 "
81 //- /main.rs
82 use test_crate::*;
83
84 //- /lib.rs
85 pub struct Baz;
86 ",
87 crate_graph! {
88 "main": ("/main.rs", ["test_crate"]),
89 "test_crate": ("/lib.rs", []),
90 },
91 );
92 assert_snapshot!(map, @r###"
93 ⋮crate
94 ⋮Baz: t v
95 "###
96 );
97}
98
99#[test]
100fn glob_enum() {
101 covers!(glob_enum);
102 let map = def_map(
103 "
104 //- /lib.rs
105 enum Foo {
106 Bar, Baz
107 }
108 use self::Foo::*;
109 ",
110 );
111 assert_snapshot!(map, @r###"
112 ⋮crate
113 ⋮Bar: t v
114 ⋮Baz: t v
115 ⋮Foo: t
116 "###
117 );
118}
diff --git a/crates/ra_hir/src/nameres/tests/incremental.rs b/crates/ra_hir/src/nameres/tests/incremental.rs
deleted file mode 100644
index af9c39760..000000000
--- a/crates/ra_hir/src/nameres/tests/incremental.rs
+++ /dev/null
@@ -1,141 +0,0 @@
1use super::*;
2
3use std::sync::Arc;
4
5use ra_db::{SourceDatabase, SourceDatabaseExt};
6
7fn check_def_map_is_not_recomputed(initial: &str, file_change: &str) {
8 let (mut db, pos) = MockDatabase::with_position(initial);
9 let crate_id = db.crate_graph().iter().next().unwrap();
10 let krate = Crate { crate_id };
11 {
12 let events = db.log_executed(|| {
13 db.crate_def_map(krate);
14 });
15 assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
16 }
17 db.set_file_text(pos.file_id, Arc::new(file_change.to_string()));
18
19 {
20 let events = db.log_executed(|| {
21 db.crate_def_map(krate);
22 });
23 assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
24 }
25}
26
27#[test]
28fn typing_inside_a_function_should_not_invalidate_def_map() {
29 check_def_map_is_not_recomputed(
30 "
31 //- /lib.rs
32 mod foo;<|>
33
34 use crate::foo::bar::Baz;
35
36 fn foo() -> i32 {
37 1 + 1
38 }
39 //- /foo/mod.rs
40 pub mod bar;
41
42 //- /foo/bar.rs
43 pub struct Baz;
44 ",
45 "
46 mod foo;
47
48 use crate::foo::bar::Baz;
49
50 fn foo() -> i32 { 92 }
51 ",
52 );
53}
54
55#[test]
56fn adding_inner_items_should_not_invalidate_def_map() {
57 check_def_map_is_not_recomputed(
58 "
59 //- /lib.rs
60 struct S { a: i32}
61 enum E { A }
62 trait T {
63 fn a() {}
64 }
65 mod foo;<|>
66 impl S {
67 fn a() {}
68 }
69 use crate::foo::bar::Baz;
70 //- /foo/mod.rs
71 pub mod bar;
72
73 //- /foo/bar.rs
74 pub struct Baz;
75 ",
76 "
77 struct S { a: i32, b: () }
78 enum E { A, B }
79 trait T {
80 fn a() {}
81 fn b() {}
82 }
83 mod foo;<|>
84 impl S {
85 fn a() {}
86 fn b() {}
87 }
88 use crate::foo::bar::Baz;
89 ",
90 );
91}
92
93#[test]
94fn typing_inside_a_macro_should_not_invalidate_def_map() {
95 let (mut db, pos) = MockDatabase::with_position(
96 "
97 //- /lib.rs
98 macro_rules! m {
99 ($ident:ident) => {
100 fn f() {
101 $ident + $ident;
102 };
103 }
104 }
105 mod foo;
106
107 //- /foo/mod.rs
108 pub mod bar;
109
110 //- /foo/bar.rs
111 <|>
112 m!(X);
113 ",
114 );
115 {
116 let events = db.log_executed(|| {
117 let src = crate::Source {
118 file_id: pos.file_id.into(),
119 ast: crate::ModuleSource::new(&db, Some(pos.file_id), None),
120 };
121 let module = crate::Module::from_definition(&db, src).unwrap();
122 let decls = module.declarations(&db);
123 assert_eq!(decls.len(), 18);
124 });
125 assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
126 }
127 db.set_file_text(pos.file_id, Arc::new("m!(Y);".to_string()));
128
129 {
130 let events = db.log_executed(|| {
131 let src = crate::Source {
132 file_id: pos.file_id.into(),
133 ast: crate::ModuleSource::new(&db, Some(pos.file_id), None),
134 };
135 let module = crate::Module::from_definition(&db, src).unwrap();
136 let decls = module.declarations(&db);
137 assert_eq!(decls.len(), 18);
138 });
139 assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
140 }
141}
diff --git a/crates/ra_hir/src/nameres/tests/macros.rs b/crates/ra_hir/src/nameres/tests/macros.rs
deleted file mode 100644
index 4f52ad2c5..000000000
--- a/crates/ra_hir/src/nameres/tests/macros.rs
+++ /dev/null
@@ -1,635 +0,0 @@
1use super::*;
2
3#[test]
4fn macro_rules_are_globally_visible() {
5 let map = def_map(
6 "
7 //- /lib.rs
8 macro_rules! structs {
9 ($($i:ident),*) => {
10 $(struct $i { field: u32 } )*
11 }
12 }
13 structs!(Foo);
14 mod nested;
15
16 //- /nested.rs
17 structs!(Bar, Baz);
18 ",
19 );
20 assert_snapshot!(map, @r###"
21 ⋮crate
22 ⋮Foo: t v
23 ⋮nested: t
24
25 ⋮crate::nested
26 ⋮Bar: t v
27 ⋮Baz: t v
28 "###);
29}
30
31#[test]
32fn macro_rules_can_define_modules() {
33 let map = def_map(
34 "
35 //- /lib.rs
36 macro_rules! m {
37 ($name:ident) => { mod $name; }
38 }
39 m!(n1);
40
41 mod m {
42 m!(n3)
43 }
44
45 //- /n1.rs
46 m!(n2)
47 //- /n1/n2.rs
48 struct X;
49 //- /m/n3.rs
50 struct Y;
51 ",
52 );
53 assert_snapshot!(map, @r###"
54 crate
55 m: t
56 n1: t
57
58 crate::m
59 n3: t
60
61 crate::m::n3
62 Y: t v
63
64 crate::n1
65 n2: t
66
67 crate::n1::n2
68 X: t v
69 "###);
70}
71
72#[test]
73fn macro_rules_from_other_crates_are_visible() {
74 let map = def_map_with_crate_graph(
75 "
76 //- /main.rs
77 foo::structs!(Foo, Bar)
78 mod bar;
79
80 //- /bar.rs
81 use crate::*;
82
83 //- /lib.rs
84 #[macro_export]
85 macro_rules! structs {
86 ($($i:ident),*) => {
87 $(struct $i { field: u32 } )*
88 }
89 }
90 ",
91 crate_graph! {
92 "main": ("/main.rs", ["foo"]),
93 "foo": ("/lib.rs", []),
94 },
95 );
96 assert_snapshot!(map, @r###"
97 ⋮crate
98 ⋮Bar: t v
99 ⋮Foo: t v
100 ⋮bar: t
101
102 ⋮crate::bar
103 ⋮Bar: t v
104 ⋮Foo: t v
105 ⋮bar: t
106 "###);
107}
108
109#[test]
110fn macro_rules_export_with_local_inner_macros_are_visible() {
111 let map = def_map_with_crate_graph(
112 "
113 //- /main.rs
114 foo::structs!(Foo, Bar)
115 mod bar;
116
117 //- /bar.rs
118 use crate::*;
119
120 //- /lib.rs
121 #[macro_export(local_inner_macros)]
122 macro_rules! structs {
123 ($($i:ident),*) => {
124 $(struct $i { field: u32 } )*
125 }
126 }
127 ",
128 crate_graph! {
129 "main": ("/main.rs", ["foo"]),
130 "foo": ("/lib.rs", []),
131 },
132 );
133 assert_snapshot!(map, @r###"
134 ⋮crate
135 ⋮Bar: t v
136 ⋮Foo: t v
137 ⋮bar: t
138
139 ⋮crate::bar
140 ⋮Bar: t v
141 ⋮Foo: t v
142 ⋮bar: t
143 "###);
144}
145
146#[test]
147fn unexpanded_macro_should_expand_by_fixedpoint_loop() {
148 let map = def_map_with_crate_graph(
149 "
150 //- /main.rs
151 macro_rules! baz {
152 () => {
153 use foo::bar;
154 }
155 }
156
157 foo!();
158 bar!();
159 baz!();
160
161 //- /lib.rs
162 #[macro_export]
163 macro_rules! foo {
164 () => {
165 struct Foo { field: u32 }
166 }
167 }
168 #[macro_export]
169 macro_rules! bar {
170 () => {
171 use foo::foo;
172 }
173 }
174 ",
175 crate_graph! {
176 "main": ("/main.rs", ["foo"]),
177 "foo": ("/lib.rs", []),
178 },
179 );
180 assert_snapshot!(map, @r###"
181 ⋮crate
182 ⋮Foo: t v
183 ⋮bar: m
184 ⋮foo: m
185 "###);
186}
187
188#[test]
189fn macro_rules_from_other_crates_are_visible_with_macro_use() {
190 covers!(macro_rules_from_other_crates_are_visible_with_macro_use);
191 let map = def_map_with_crate_graph(
192 "
193 //- /main.rs
194 structs!(Foo);
195 structs_priv!(Bar);
196 structs_not_exported!(MacroNotResolved1);
197 crate::structs!(MacroNotResolved2);
198
199 mod bar;
200
201 #[macro_use]
202 extern crate foo;
203
204 //- /bar.rs
205 structs!(Baz);
206 crate::structs!(MacroNotResolved3);
207
208 //- /lib.rs
209 #[macro_export]
210 macro_rules! structs {
211 ($i:ident) => { struct $i; }
212 }
213
214 macro_rules! structs_not_exported {
215 ($i:ident) => { struct $i; }
216 }
217
218 mod priv_mod {
219 #[macro_export]
220 macro_rules! structs_priv {
221 ($i:ident) => { struct $i; }
222 }
223 }
224 ",
225 crate_graph! {
226 "main": ("/main.rs", ["foo"]),
227 "foo": ("/lib.rs", []),
228 },
229 );
230 assert_snapshot!(map, @r###"
231 ⋮crate
232 ⋮Bar: t v
233 ⋮Foo: t v
234 ⋮bar: t
235 ⋮foo: t
236
237 ⋮crate::bar
238 ⋮Baz: t v
239 "###);
240}
241
242#[test]
243fn prelude_is_macro_use() {
244 covers!(prelude_is_macro_use);
245 let map = def_map_with_crate_graph(
246 "
247 //- /main.rs
248 structs!(Foo);
249 structs_priv!(Bar);
250 structs_outside!(Out);
251 crate::structs!(MacroNotResolved2);
252
253 mod bar;
254
255 //- /bar.rs
256 structs!(Baz);
257 crate::structs!(MacroNotResolved3);
258
259 //- /lib.rs
260 #[prelude_import]
261 use self::prelude::*;
262
263 mod prelude {
264 #[macro_export]
265 macro_rules! structs {
266 ($i:ident) => { struct $i; }
267 }
268
269 mod priv_mod {
270 #[macro_export]
271 macro_rules! structs_priv {
272 ($i:ident) => { struct $i; }
273 }
274 }
275 }
276
277 #[macro_export]
278 macro_rules! structs_outside {
279 ($i:ident) => { struct $i; }
280 }
281 ",
282 crate_graph! {
283 "main": ("/main.rs", ["foo"]),
284 "foo": ("/lib.rs", []),
285 },
286 );
287 assert_snapshot!(map, @r###"
288 ⋮crate
289 ⋮Bar: t v
290 ⋮Foo: t v
291 ⋮Out: t v
292 ⋮bar: t
293
294 ⋮crate::bar
295 ⋮Baz: t v
296 "###);
297}
298
299#[test]
300fn prelude_cycle() {
301 let map = def_map(
302 "
303 //- /lib.rs
304 #[prelude_import]
305 use self::prelude::*;
306
307 declare_mod!();
308
309 mod prelude {
310 macro_rules! declare_mod {
311 () => (mod foo {})
312 }
313 }
314 ",
315 );
316 assert_snapshot!(map, @r###"
317 ⋮crate
318 ⋮prelude: t
319
320 ⋮crate::prelude
321 "###);
322}
323
324#[test]
325fn plain_macros_are_legacy_textual_scoped() {
326 let map = def_map(
327 r#"
328 //- /main.rs
329 mod m1;
330 bar!(NotFoundNotMacroUse);
331
332 mod m2 {
333 foo!(NotFoundBeforeInside2);
334 }
335
336 macro_rules! foo {
337 ($x:ident) => { struct $x; }
338 }
339 foo!(Ok);
340
341 mod m3;
342 foo!(OkShadowStop);
343 bar!(NotFoundMacroUseStop);
344
345 #[macro_use]
346 mod m5 {
347 #[macro_use]
348 mod m6 {
349 macro_rules! foo {
350 ($x:ident) => { fn $x() {} }
351 }
352 }
353 }
354 foo!(ok_double_macro_use_shadow);
355
356 baz!(NotFoundBefore);
357 #[macro_use]
358 mod m7 {
359 macro_rules! baz {
360 ($x:ident) => { struct $x; }
361 }
362 }
363 baz!(OkAfter);
364
365 //- /m1.rs
366 foo!(NotFoundBeforeInside1);
367 macro_rules! bar {
368 ($x:ident) => { struct $x; }
369 }
370
371 //- /m3/mod.rs
372 foo!(OkAfterInside);
373 macro_rules! foo {
374 ($x:ident) => { fn $x() {} }
375 }
376 foo!(ok_shadow);
377
378 #[macro_use]
379 mod m4;
380 bar!(OkMacroUse);
381
382 //- /m3/m4.rs
383 foo!(ok_shadow_deep);
384 macro_rules! bar {
385 ($x:ident) => { struct $x; }
386 }
387 "#,
388 );
389 assert_snapshot!(map, @r###"
390 ⋮crate
391 ⋮Ok: t v
392 ⋮OkAfter: t v
393 ⋮OkShadowStop: t v
394 ⋮m1: t
395 ⋮m2: t
396 ⋮m3: t
397 ⋮m5: t
398 ⋮m7: t
399 ⋮ok_double_macro_use_shadow: v
400
401 ⋮crate::m7
402
403 ⋮crate::m1
404
405 ⋮crate::m5
406 ⋮m6: t
407
408 ⋮crate::m5::m6
409
410 ⋮crate::m2
411
412 ⋮crate::m3
413 ⋮OkAfterInside: t v
414 ⋮OkMacroUse: t v
415 ⋮m4: t
416 ⋮ok_shadow: v
417
418 ⋮crate::m3::m4
419 ⋮ok_shadow_deep: v
420 "###);
421}
422
423#[test]
424fn type_value_macro_live_in_different_scopes() {
425 let map = def_map(
426 "
427 //- /main.rs
428 #[macro_export]
429 macro_rules! foo {
430 ($x:ident) => { type $x = (); }
431 }
432
433 foo!(foo);
434 use foo as bar;
435
436 use self::foo as baz;
437 fn baz() {}
438 ",
439 );
440 assert_snapshot!(map, @r###"
441 ⋮crate
442 ⋮bar: t m
443 ⋮baz: t v m
444 ⋮foo: t m
445 "###);
446}
447
448#[test]
449fn macro_use_can_be_aliased() {
450 let map = def_map_with_crate_graph(
451 "
452 //- /main.rs
453 #[macro_use]
454 extern crate foo;
455
456 foo!(Direct);
457 bar!(Alias);
458
459 //- /lib.rs
460 use crate::foo as bar;
461
462 mod m {
463 #[macro_export]
464 macro_rules! foo {
465 ($x:ident) => { struct $x; }
466 }
467 }
468 ",
469 crate_graph! {
470 "main": ("/main.rs", ["foo"]),
471 "foo": ("/lib.rs", []),
472 },
473 );
474 assert_snapshot!(map, @r###"
475 ⋮crate
476 ⋮Alias: t v
477 ⋮Direct: t v
478 ⋮foo: t
479 "###);
480}
481
482#[test]
483fn path_qualified_macros() {
484 let map = def_map(
485 "
486 //- /main.rs
487 macro_rules! foo {
488 ($x:ident) => { struct $x; }
489 }
490
491 crate::foo!(NotResolved);
492
493 crate::bar!(OkCrate);
494 bar!(OkPlain);
495 alias1!(NotHere);
496 m::alias1!(OkAliasPlain);
497 m::alias2!(OkAliasSuper);
498 m::alias3!(OkAliasCrate);
499 not_found!(NotFound);
500
501 mod m {
502 #[macro_export]
503 macro_rules! bar {
504 ($x:ident) => { struct $x; }
505 }
506
507 pub use bar as alias1;
508 pub use super::bar as alias2;
509 pub use crate::bar as alias3;
510 pub use self::bar as not_found;
511 }
512 ",
513 );
514 assert_snapshot!(map, @r###"
515 ⋮crate
516 ⋮OkAliasCrate: t v
517 ⋮OkAliasPlain: t v
518 ⋮OkAliasSuper: t v
519 ⋮OkCrate: t v
520 ⋮OkPlain: t v
521 ⋮bar: m
522 ⋮m: t
523
524 ⋮crate::m
525 ⋮alias1: m
526 ⋮alias2: m
527 ⋮alias3: m
528 ⋮not_found: _
529 "###);
530}
531
532#[test]
533fn macro_dollar_crate_is_correct_in_item() {
534 covers!(macro_dollar_crate_self);
535 covers!(macro_dollar_crate_other);
536 let map = def_map_with_crate_graph(
537 "
538 //- /main.rs
539 #[macro_use]
540 extern crate foo;
541
542 #[macro_use]
543 mod m {
544 macro_rules! current {
545 () => {
546 use $crate::Foo as FooSelf;
547 }
548 }
549 }
550
551 struct Foo;
552
553 current!();
554 not_current1!();
555 foo::not_current2!();
556
557 //- /lib.rs
558 mod m {
559 #[macro_export]
560 macro_rules! not_current1 {
561 () => {
562 use $crate::Bar;
563 }
564 }
565 }
566
567 #[macro_export]
568 macro_rules! not_current2 {
569 () => {
570 use $crate::Baz;
571 }
572 }
573
574 struct Bar;
575 struct Baz;
576 ",
577 crate_graph! {
578 "main": ("/main.rs", ["foo"]),
579 "foo": ("/lib.rs", []),
580 },
581 );
582 assert_snapshot!(map, @r###"
583 ⋮crate
584 ⋮Bar: t v
585 ⋮Baz: t v
586 ⋮Foo: t v
587 ⋮FooSelf: t v
588 ⋮foo: t
589 ⋮m: t
590
591 ⋮crate::m
592 "###);
593}
594
595#[test]
596fn macro_dollar_crate_is_correct_in_indirect_deps() {
597 covers!(macro_dollar_crate_other);
598 // From std
599 let map = def_map_with_crate_graph(
600 r#"
601 //- /main.rs
602 foo!();
603
604 //- /std.rs
605 #[prelude_import]
606 use self::prelude::*;
607
608 pub use core::foo;
609
610 mod prelude {}
611
612 #[macro_use]
613 mod std_macros;
614
615 //- /core.rs
616 #[macro_export]
617 macro_rules! foo {
618 () => {
619 use $crate::bar;
620 }
621 }
622
623 pub struct bar;
624 "#,
625 crate_graph! {
626 "main": ("/main.rs", ["std"]),
627 "std": ("/std.rs", ["core"]),
628 "core": ("/core.rs", []),
629 },
630 );
631 assert_snapshot!(map, @r###"
632 ⋮crate
633 ⋮bar: t v
634 "###);
635}
diff --git a/crates/ra_hir/src/nameres/tests/mod_resolution.rs b/crates/ra_hir/src/nameres/tests/mod_resolution.rs
deleted file mode 100644
index abfe8b1c3..000000000
--- a/crates/ra_hir/src/nameres/tests/mod_resolution.rs
+++ /dev/null
@@ -1,759 +0,0 @@
1use super::*;
2
3#[test]
4fn name_res_works_for_broken_modules() {
5 // covers!(name_res_works_for_broken_modules);
6 let map = def_map(
7 "
8 //- /lib.rs
9 mod foo // no `;`, no body
10
11 use self::foo::Baz;
12
13 //- /foo/mod.rs
14 pub mod bar;
15
16 pub use self::bar::Baz;
17
18 //- /foo/bar.rs
19 pub struct Baz;
20 ",
21 );
22 assert_snapshot!(map, @r###"
23 ⋮crate
24 ⋮Baz: _
25 "###);
26}
27
28#[test]
29fn nested_module_resolution() {
30 let map = def_map(
31 "
32 //- /lib.rs
33 mod n1;
34
35 //- /n1.rs
36 mod n2;
37
38 //- /n1/n2.rs
39 struct X;
40 ",
41 );
42
43 assert_snapshot!(map, @r###"
44 ⋮crate
45 ⋮n1: t
46
47 ⋮crate::n1
48 ⋮n2: t
49
50 ⋮crate::n1::n2
51 ⋮X: t v
52 "###);
53}
54
55#[test]
56fn module_resolution_works_for_non_standard_filenames() {
57 let map = def_map_with_crate_graph(
58 "
59 //- /my_library.rs
60 mod foo;
61 use self::foo::Bar;
62
63 //- /foo/mod.rs
64 pub struct Bar;
65 ",
66 crate_graph! {
67 "my_library": ("/my_library.rs", []),
68 },
69 );
70
71 assert_snapshot!(map, @r###"
72 ⋮crate
73 ⋮Bar: t v
74 ⋮foo: t
75
76 ⋮crate::foo
77 ⋮Bar: t v
78 "###);
79}
80
81#[test]
82fn module_resolution_works_for_raw_modules() {
83 let map = def_map(
84 "
85 //- /lib.rs
86 mod r#async;
87 use self::r#async::Bar;
88
89 //- /async.rs
90 pub struct Bar;
91 ",
92 );
93
94 assert_snapshot!(map, @r###"
95 ⋮crate
96 ⋮Bar: t v
97 ⋮async: t
98
99 ⋮crate::async
100 ⋮Bar: t v
101 "###);
102}
103
104#[test]
105fn module_resolution_decl_path() {
106 let map = def_map(
107 r###"
108 //- /lib.rs
109 #[path = "bar/baz/foo.rs"]
110 mod foo;
111 use self::foo::Bar;
112
113 //- /bar/baz/foo.rs
114 pub struct Bar;
115 "###,
116 );
117
118 assert_snapshot!(map, @r###"
119 ⋮crate
120 ⋮Bar: t v
121 ⋮foo: t
122
123 ⋮crate::foo
124 ⋮Bar: t v
125 "###);
126}
127
128#[test]
129fn module_resolution_module_with_path_in_mod_rs() {
130 let map = def_map(
131 r###"
132 //- /main.rs
133 mod foo;
134
135 //- /foo/mod.rs
136 #[path = "baz.rs"]
137 pub mod bar;
138
139 use self::bar::Baz;
140
141 //- /foo/baz.rs
142 pub struct Baz;
143 "###,
144 );
145
146 assert_snapshot!(map, @r###"
147 ⋮crate
148 ⋮foo: t
149
150 ⋮crate::foo
151 ⋮Baz: t v
152 ⋮bar: t
153
154 ⋮crate::foo::bar
155 ⋮Baz: t v
156 "###);
157}
158
159#[test]
160fn module_resolution_module_with_path_non_crate_root() {
161 let map = def_map(
162 r###"
163 //- /main.rs
164 mod foo;
165
166 //- /foo.rs
167 #[path = "baz.rs"]
168 pub mod bar;
169
170 use self::bar::Baz;
171
172 //- /baz.rs
173 pub struct Baz;
174 "###,
175 );
176
177 assert_snapshot!(map, @r###"
178 ⋮crate
179 ⋮foo: t
180
181 ⋮crate::foo
182 ⋮Baz: t v
183 ⋮bar: t
184
185 ⋮crate::foo::bar
186 ⋮Baz: t v
187 "###);
188}
189
190#[test]
191fn module_resolution_module_decl_path_super() {
192 let map = def_map(
193 r###"
194 //- /main.rs
195 #[path = "bar/baz/module.rs"]
196 mod foo;
197 pub struct Baz;
198
199 //- /bar/baz/module.rs
200 use super::Baz;
201 "###,
202 );
203
204 assert_snapshot!(map, @r###"
205 ⋮crate
206 ⋮Baz: t v
207 ⋮foo: t
208
209 ⋮crate::foo
210 ⋮Baz: t v
211 "###);
212}
213
214#[test]
215fn module_resolution_explicit_path_mod_rs() {
216 let map = def_map(
217 r###"
218 //- /main.rs
219 #[path = "module/mod.rs"]
220 mod foo;
221
222 //- /module/mod.rs
223 pub struct Baz;
224 "###,
225 );
226
227 assert_snapshot!(map, @r###"
228 ⋮crate
229 ⋮foo: t
230
231 ⋮crate::foo
232 ⋮Baz: t v
233 "###);
234}
235
236#[test]
237fn module_resolution_relative_path() {
238 let map = def_map(
239 r###"
240 //- /main.rs
241 mod foo;
242
243 //- /foo.rs
244 #[path = "./sub.rs"]
245 pub mod foo_bar;
246
247 //- /sub.rs
248 pub struct Baz;
249 "###,
250 );
251
252 assert_snapshot!(map, @r###"
253 ⋮crate
254 ⋮foo: t
255
256 ⋮crate::foo
257 ⋮foo_bar: t
258
259 ⋮crate::foo::foo_bar
260 ⋮Baz: t v
261 "###);
262}
263
264#[test]
265fn module_resolution_relative_path_2() {
266 let map = def_map(
267 r###"
268 //- /main.rs
269 mod foo;
270
271 //- /foo/mod.rs
272 #[path="../sub.rs"]
273 pub mod foo_bar;
274
275 //- /sub.rs
276 pub struct Baz;
277 "###,
278 );
279
280 assert_snapshot!(map, @r###"
281 ⋮crate
282 ⋮foo: t
283
284 ⋮crate::foo
285 ⋮foo_bar: t
286
287 ⋮crate::foo::foo_bar
288 ⋮Baz: t v
289 "###);
290}
291
292#[test]
293fn module_resolution_explicit_path_mod_rs_2() {
294 let map = def_map(
295 r###"
296 //- /main.rs
297 #[path = "module/bar/mod.rs"]
298 mod foo;
299
300 //- /module/bar/mod.rs
301 pub struct Baz;
302 "###,
303 );
304
305 assert_snapshot!(map, @r###"
306 ⋮crate
307 ⋮foo: t
308
309 ⋮crate::foo
310 ⋮Baz: t v
311 "###);
312}
313
314#[test]
315fn module_resolution_explicit_path_mod_rs_with_win_separator() {
316 let map = def_map(
317 r###"
318 //- /main.rs
319 #[path = "module\bar\mod.rs"]
320 mod foo;
321
322 //- /module/bar/mod.rs
323 pub struct Baz;
324 "###,
325 );
326
327 assert_snapshot!(map, @r###"
328 ⋮crate
329 ⋮foo: t
330
331 ⋮crate::foo
332 ⋮Baz: t v
333 "###);
334}
335
336#[test]
337fn module_resolution_decl_inside_inline_module_with_path_attribute() {
338 let map = def_map(
339 r###"
340 //- /main.rs
341 #[path = "models"]
342 mod foo {
343 mod bar;
344 }
345
346 //- /models/bar.rs
347 pub struct Baz;
348 "###,
349 );
350
351 assert_snapshot!(map, @r###"
352 ⋮crate
353 ⋮foo: t
354
355 ⋮crate::foo
356 ⋮bar: t
357
358 ⋮crate::foo::bar
359 ⋮Baz: t v
360 "###);
361}
362
363#[test]
364fn module_resolution_decl_inside_inline_module() {
365 let map = def_map(
366 r###"
367 //- /main.rs
368 mod foo {
369 mod bar;
370 }
371
372 //- /foo/bar.rs
373 pub struct Baz;
374 "###,
375 );
376
377 assert_snapshot!(map, @r###"
378 ⋮crate
379 ⋮foo: t
380
381 ⋮crate::foo
382 ⋮bar: t
383
384 ⋮crate::foo::bar
385 ⋮Baz: t v
386 "###);
387}
388
389#[test]
390fn module_resolution_decl_inside_inline_module_2_with_path_attribute() {
391 let map = def_map(
392 r###"
393 //- /main.rs
394 #[path = "models/db"]
395 mod foo {
396 mod bar;
397 }
398
399 //- /models/db/bar.rs
400 pub struct Baz;
401 "###,
402 );
403
404 assert_snapshot!(map, @r###"
405 ⋮crate
406 ⋮foo: t
407
408 ⋮crate::foo
409 ⋮bar: t
410
411 ⋮crate::foo::bar
412 ⋮Baz: t v
413 "###);
414}
415
416#[test]
417fn module_resolution_decl_inside_inline_module_3() {
418 let map = def_map(
419 r###"
420 //- /main.rs
421 #[path = "models/db"]
422 mod foo {
423 #[path = "users.rs"]
424 mod bar;
425 }
426
427 //- /models/db/users.rs
428 pub struct Baz;
429 "###,
430 );
431
432 assert_snapshot!(map, @r###"
433 ⋮crate
434 ⋮foo: t
435
436 ⋮crate::foo
437 ⋮bar: t
438
439 ⋮crate::foo::bar
440 ⋮Baz: t v
441 "###);
442}
443
444#[test]
445fn module_resolution_decl_inside_inline_module_empty_path() {
446 let map = def_map(
447 r###"
448 //- /main.rs
449 #[path = ""]
450 mod foo {
451 #[path = "users.rs"]
452 mod bar;
453 }
454
455 //- /users.rs
456 pub struct Baz;
457 "###,
458 );
459
460 assert_snapshot!(map, @r###"
461 ⋮crate
462 ⋮foo: t
463
464 ⋮crate::foo
465 ⋮bar: t
466
467 ⋮crate::foo::bar
468 ⋮Baz: t v
469 "###);
470}
471
472#[test]
473fn module_resolution_decl_empty_path() {
474 let map = def_map(
475 r###"
476 //- /main.rs
477 #[path = ""] // Should try to read `/` (a directory)
478 mod foo;
479
480 //- /foo.rs
481 pub struct Baz;
482 "###,
483 );
484
485 assert_snapshot!(map, @r###"
486 ⋮crate
487 "###);
488}
489
490#[test]
491fn module_resolution_decl_inside_inline_module_relative_path() {
492 let map = def_map(
493 r###"
494 //- /main.rs
495 #[path = "./models"]
496 mod foo {
497 mod bar;
498 }
499
500 //- /models/bar.rs
501 pub struct Baz;
502 "###,
503 );
504
505 assert_snapshot!(map, @r###"
506 ⋮crate
507 ⋮foo: t
508
509 ⋮crate::foo
510 ⋮bar: t
511
512 ⋮crate::foo::bar
513 ⋮Baz: t v
514 "###);
515}
516
517#[test]
518fn module_resolution_decl_inside_inline_module_in_crate_root() {
519 let map = def_map(
520 r###"
521 //- /main.rs
522 mod foo {
523 #[path = "baz.rs"]
524 mod bar;
525 }
526 use self::foo::bar::Baz;
527
528 //- /foo/baz.rs
529 pub struct Baz;
530 "###,
531 );
532
533 assert_snapshot!(map, @r###"
534 ⋮crate
535 ⋮Baz: t v
536 ⋮foo: t
537
538 ⋮crate::foo
539 ⋮bar: t
540
541 ⋮crate::foo::bar
542 ⋮Baz: t v
543 "###);
544}
545
546#[test]
547fn module_resolution_decl_inside_inline_module_in_mod_rs() {
548 let map = def_map(
549 r###"
550 //- /main.rs
551 mod foo;
552
553 //- /foo/mod.rs
554 mod bar {
555 #[path = "qwe.rs"]
556 pub mod baz;
557 }
558 use self::bar::baz::Baz;
559
560 //- /foo/bar/qwe.rs
561 pub struct Baz;
562 "###,
563 );
564
565 assert_snapshot!(map, @r###"
566 ⋮crate
567 ⋮foo: t
568
569 ⋮crate::foo
570 ⋮Baz: t v
571 ⋮bar: t
572
573 ⋮crate::foo::bar
574 ⋮baz: t
575
576 ⋮crate::foo::bar::baz
577 ⋮Baz: t v
578 "###);
579}
580
581#[test]
582fn module_resolution_decl_inside_inline_module_in_non_crate_root() {
583 let map = def_map(
584 r###"
585 //- /main.rs
586 mod foo;
587
588 //- /foo.rs
589 mod bar {
590 #[path = "qwe.rs"]
591 pub mod baz;
592 }
593 use self::bar::baz::Baz;
594
595 //- /foo/bar/qwe.rs
596 pub struct Baz;
597 "###,
598 );
599
600 assert_snapshot!(map, @r###"
601 ⋮crate
602 ⋮foo: t
603
604 ⋮crate::foo
605 ⋮Baz: t v
606 ⋮bar: t
607
608 ⋮crate::foo::bar
609 ⋮baz: t
610
611 ⋮crate::foo::bar::baz
612 ⋮Baz: t v
613 "###);
614}
615
616#[test]
617fn module_resolution_decl_inside_inline_module_in_non_crate_root_2() {
618 let map = def_map(
619 r###"
620 //- /main.rs
621 mod foo;
622
623 //- /foo.rs
624 #[path = "bar"]
625 mod bar {
626 pub mod baz;
627 }
628 use self::bar::baz::Baz;
629
630 //- /bar/baz.rs
631 pub struct Baz;
632 "###,
633 );
634
635 assert_snapshot!(map, @r###"
636 ⋮crate
637 ⋮foo: t
638
639 ⋮crate::foo
640 ⋮Baz: t v
641 ⋮bar: t
642
643 ⋮crate::foo::bar
644 ⋮baz: t
645
646 ⋮crate::foo::bar::baz
647 ⋮Baz: t v
648 "###);
649}
650
651#[test]
652fn unresolved_module_diagnostics() {
653 let diagnostics = MockDatabase::with_files(
654 r"
655 //- /lib.rs
656 mod foo;
657 mod bar;
658 mod baz {}
659 //- /foo.rs
660 ",
661 )
662 .diagnostics();
663
664 assert_snapshot!(diagnostics, @r###"
665 "mod bar;": unresolved module
666 "###
667 );
668}
669
670#[test]
671fn module_resolution_decl_inside_module_in_non_crate_root_2() {
672 let map = def_map(
673 r###"
674 //- /main.rs
675 #[path="module/m2.rs"]
676 mod module;
677
678 //- /module/m2.rs
679 pub mod submod;
680
681 //- /module/submod.rs
682 pub struct Baz;
683 "###,
684 );
685
686 assert_snapshot!(map, @r###"
687 ⋮crate
688 ⋮module: t
689
690 ⋮crate::module
691 ⋮submod: t
692
693 ⋮crate::module::submod
694 ⋮Baz: t v
695 "###);
696}
697
698#[test]
699fn nested_out_of_line_module() {
700 let map = def_map(
701 r###"
702 //- /lib.rs
703 mod a {
704 mod b {
705 mod c;
706 }
707 }
708
709 //- /a/b/c.rs
710 struct X;
711 "###,
712 );
713
714 assert_snapshot!(map, @r###"
715 crate
716 a: t
717
718 crate::a
719 b: t
720
721 crate::a::b
722 c: t
723
724 crate::a::b::c
725 X: t v
726 "###);
727}
728
729#[test]
730fn nested_out_of_line_module_with_path() {
731 let map = def_map(
732 r###"
733 //- /lib.rs
734 mod a {
735 #[path = "d/e"]
736 mod b {
737 mod c;
738 }
739 }
740
741 //- /a/d/e/c.rs
742 struct X;
743 "###,
744 );
745
746 assert_snapshot!(map, @r###"
747 crate
748 a: t
749
750 crate::a
751 b: t
752
753 crate::a::b
754 c: t
755
756 crate::a::b::c
757 X: t v
758 "###);
759}
diff --git a/crates/ra_hir/src/nameres/tests/primitives.rs b/crates/ra_hir/src/nameres/tests/primitives.rs
deleted file mode 100644
index 0e2708658..000000000
--- a/crates/ra_hir/src/nameres/tests/primitives.rs
+++ /dev/null
@@ -1,24 +0,0 @@
1use super::*;
2
3#[test]
4fn primitive_reexport() {
5 let map = def_map(
6 "
7 //- /lib.rs
8 mod foo;
9 use foo::int;
10
11 //- /foo.rs
12 pub use i32 as int;
13 ",
14 );
15 assert_snapshot!(map, @r###"
16 ⋮crate
17 ⋮foo: t
18 ⋮int: t
19
20 ⋮crate::foo
21 ⋮int: t
22 "###
23 );
24}