@@ -8,8 +8,6 @@ use crate::{
8
8
} ;
9
9
use hir_expand:: name:: Name ;
10
10
11
- // TODO don't import from super imports? or at least deprioritize
12
- // TODO use super?
13
11
// TODO performance / memoize
14
12
15
13
pub fn find_path ( db : & impl DefDatabase , item : ItemInNs , from : ModuleId ) -> Option < ModPath > {
@@ -27,6 +25,13 @@ pub fn find_path(db: &impl DefDatabase, item: ItemInNs, from: ModuleId) -> Optio
27
25
return Some ( ModPath :: from_simple_segments ( PathKind :: Crate , Vec :: new ( ) ) ) ;
28
26
}
29
27
28
+ // - if the item is the parent module, use `super` (this is not used recursively, since `super::super` is ugly)
29
+ if let Some ( parent_id) = def_map. modules [ from. local_id ] . parent {
30
+ if item == ItemInNs :: Types ( ModuleDefId :: ModuleId ( ModuleId { krate : from. krate , local_id : parent_id } ) ) {
31
+ return Some ( ModPath :: from_simple_segments ( PathKind :: Super ( 1 ) , Vec :: new ( ) ) ) ;
32
+ }
33
+ }
34
+
30
35
// - if the item is the crate root of a dependency crate, return the name from the extern prelude
31
36
for ( name, def_id) in & def_map. extern_prelude {
32
37
if item == ItemInNs :: Types ( * def_id) {
@@ -80,6 +85,19 @@ fn find_importable_locations(db: &impl DefDatabase, item: ItemInNs, from: Module
80
85
let def_map = db. crate_def_map ( krate) ;
81
86
for ( local_id, data) in def_map. modules . iter ( ) {
82
87
if let Some ( ( name, vis) ) = data. scope . reverse_get ( item) {
88
+ let is_private = if let crate :: visibility:: Visibility :: Module ( private_to) = vis {
89
+ private_to. local_id == local_id
90
+ } else { false } ;
91
+ let is_original_def = if let Some ( module_def_id) = item. as_module_def_id ( ) {
92
+ data. scope . declarations ( ) . any ( |it| it == module_def_id)
93
+ } else { false } ;
94
+ if is_private && !is_original_def {
95
+ // Ignore private imports. these could be used if we are
96
+ // in a submodule of this module, but that's usually not
97
+ // what the user wants; and if this module can import
98
+ // the item and we're a submodule of it, so can we.
99
+ continue ;
100
+ }
83
101
if vis. is_visible_from ( db, from) {
84
102
result. push ( ( ModuleId { krate, local_id } , name. clone ( ) ) ) ;
85
103
}
@@ -160,6 +178,20 @@ mod tests {
160
178
check_found_path ( code, "foo::S" ) ;
161
179
}
162
180
181
+ #[ test]
182
+ fn super_module ( ) {
183
+ let code = r#"
184
+ //- /main.rs
185
+ mod foo;
186
+ //- /foo.rs
187
+ mod bar;
188
+ struct S;
189
+ //- /foo/bar.rs
190
+ <|>
191
+ "# ;
192
+ check_found_path ( code, "super::S" ) ;
193
+ }
194
+
163
195
#[ test]
164
196
fn crate_root ( ) {
165
197
let code = r#"
@@ -290,4 +322,18 @@ mod tests {
290
322
"# ;
291
323
check_found_path ( code, "baz::S" ) ;
292
324
}
325
+
326
+ #[ test]
327
+ fn discount_private_imports ( ) {
328
+ let code = r#"
329
+ //- /main.rs
330
+ mod foo;
331
+ pub mod bar { pub struct S; }
332
+ use bar::S;
333
+ //- /foo.rs
334
+ <|>
335
+ "# ;
336
+ // crate::S would be shorter, but using private imports seems wrong
337
+ check_found_path ( code, "crate::bar::S" ) ;
338
+ }
293
339
}
0 commit comments