diff options
-rw-r--r-- | crates/hir_def/src/nameres.rs | 6 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 4 | ||||
-rw-r--r-- | crates/hir_def/src/visibility.rs | 36 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/dot.rs | 28 |
4 files changed, 65 insertions, 9 deletions
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index 34ff07f3c..f92232eb3 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -337,6 +337,12 @@ impl DefMap { | |||
337 | None | 337 | None |
338 | } | 338 | } |
339 | 339 | ||
340 | /// If this `DefMap` is for a block expression, returns the module containing the block (which | ||
341 | /// might again be a block, or a module inside a block). | ||
342 | pub fn parent(&self) -> Option<ModuleId> { | ||
343 | Some(self.block?.parent) | ||
344 | } | ||
345 | |||
340 | // FIXME: this can use some more human-readable format (ideally, an IR | 346 | // FIXME: this can use some more human-readable format (ideally, an IR |
341 | // even), as this should be a great debugging aid. | 347 | // even), as this should be a great debugging aid. |
342 | pub fn dump(&self, db: &dyn DefDatabase) -> String { | 348 | pub fn dump(&self, db: &dyn DefDatabase) -> String { |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 6bd41bc08..9996a0807 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -608,7 +608,7 @@ impl DefCollector<'_> { | |||
608 | ( | 608 | ( |
609 | n, | 609 | n, |
610 | res.filter_visibility(|v| { | 610 | res.filter_visibility(|v| { |
611 | v.is_visible_from_def_map(&self.def_map, module_id) | 611 | v.is_visible_from_def_map(self.db, &self.def_map, module_id) |
612 | }), | 612 | }), |
613 | ) | 613 | ) |
614 | }) | 614 | }) |
@@ -761,7 +761,7 @@ impl DefCollector<'_> { | |||
761 | .filter(|(glob_importing_module, _)| { | 761 | .filter(|(glob_importing_module, _)| { |
762 | // we know all resolutions have the same visibility (`vis`), so we | 762 | // we know all resolutions have the same visibility (`vis`), so we |
763 | // just need to check that once | 763 | // just need to check that once |
764 | vis.is_visible_from_def_map(&self.def_map, *glob_importing_module) | 764 | vis.is_visible_from_def_map(self.db, &self.def_map, *glob_importing_module) |
765 | }) | 765 | }) |
766 | .cloned() | 766 | .cloned() |
767 | .collect::<Vec<_>>(); | 767 | .collect::<Vec<_>>(); |
diff --git a/crates/hir_def/src/visibility.rs b/crates/hir_def/src/visibility.rs index 38da3132b..0e3951910 100644 --- a/crates/hir_def/src/visibility.rs +++ b/crates/hir_def/src/visibility.rs | |||
@@ -103,7 +103,7 @@ impl Visibility { | |||
103 | return false; | 103 | return false; |
104 | } | 104 | } |
105 | let def_map = from_module.def_map(db); | 105 | let def_map = from_module.def_map(db); |
106 | self.is_visible_from_def_map(&def_map, from_module.local_id) | 106 | self.is_visible_from_def_map(db, &def_map, from_module.local_id) |
107 | } | 107 | } |
108 | 108 | ||
109 | pub(crate) fn is_visible_from_other_crate(self) -> bool { | 109 | pub(crate) fn is_visible_from_other_crate(self) -> bool { |
@@ -115,19 +115,41 @@ impl Visibility { | |||
115 | 115 | ||
116 | pub(crate) fn is_visible_from_def_map( | 116 | pub(crate) fn is_visible_from_def_map( |
117 | self, | 117 | self, |
118 | db: &dyn DefDatabase, | ||
118 | def_map: &DefMap, | 119 | def_map: &DefMap, |
119 | from_module: crate::LocalModuleId, | 120 | mut from_module: crate::LocalModuleId, |
120 | ) -> bool { | 121 | ) -> bool { |
121 | let to_module = match self { | 122 | let to_module = match self { |
122 | Visibility::Module(m) => m, | 123 | Visibility::Module(m) => m, |
123 | Visibility::Public => return true, | 124 | Visibility::Public => return true, |
124 | }; | 125 | }; |
126 | |||
125 | // from_module needs to be a descendant of to_module | 127 | // from_module needs to be a descendant of to_module |
126 | let mut ancestors = std::iter::successors(Some(from_module), |m| { | 128 | let mut def_map = def_map; |
127 | let parent_id = def_map[*m].parent?; | 129 | let mut parent_arc; |
128 | Some(parent_id) | 130 | loop { |
129 | }); | 131 | if def_map.module_id(from_module) == to_module { |
130 | ancestors.any(|m| m == to_module.local_id) | 132 | return true; |
133 | } | ||
134 | match def_map[from_module].parent { | ||
135 | Some(parent) => { | ||
136 | from_module = parent; | ||
137 | } | ||
138 | None => { | ||
139 | match def_map.parent() { | ||
140 | Some(module) => { | ||
141 | parent_arc = module.def_map(db); | ||
142 | def_map = &*parent_arc; | ||
143 | from_module = module.local_id; | ||
144 | } | ||
145 | None => { | ||
146 | // Reached the root module, nothing left to check. | ||
147 | return false; | ||
148 | } | ||
149 | } | ||
150 | } | ||
151 | } | ||
152 | } | ||
131 | } | 153 | } |
132 | 154 | ||
133 | /// Returns the most permissive visibility of `self` and `other`. | 155 | /// Returns the most permissive visibility of `self` and `other`. |
diff --git a/crates/ide_completion/src/completions/dot.rs b/crates/ide_completion/src/completions/dot.rs index 0880a3830..084d7721d 100644 --- a/crates/ide_completion/src/completions/dot.rs +++ b/crates/ide_completion/src/completions/dot.rs | |||
@@ -428,4 +428,32 @@ fn main() { make_s!().f$0; } | |||
428 | "#]], | 428 | "#]], |
429 | ) | 429 | ) |
430 | } | 430 | } |
431 | |||
432 | #[test] | ||
433 | fn completes_after_macro_call_in_submodule() { | ||
434 | check( | ||
435 | r#" | ||
436 | macro_rules! empty { | ||
437 | () => {}; | ||
438 | } | ||
439 | |||
440 | mod foo { | ||
441 | #[derive(Debug, Default)] | ||
442 | struct Template2 {} | ||
443 | |||
444 | impl Template2 { | ||
445 | fn private(&self) {} | ||
446 | } | ||
447 | fn baz() { | ||
448 | let goo: Template2 = Template2 {}; | ||
449 | empty!(); | ||
450 | goo.$0 | ||
451 | } | ||
452 | } | ||
453 | "#, | ||
454 | expect![[r#" | ||
455 | me private() -> () | ||
456 | "#]], | ||
457 | ); | ||
458 | } | ||
431 | } | 459 | } |