about summary refs log tree commit diff
path: root/crates/hir-def/src/find_path.rs
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-01-11 09:54:22 +0000
committerbors <bors@rust-lang.org>2024-01-11 09:54:22 +0000
commitd5366b5c19c28270dfcce4cb15c90fc7cf194a60 (patch)
tree28a3a508762e015e0899a930869cc32ae575231a /crates/hir-def/src/find_path.rs
parente4344f5fce3b4ca12d51bf27b9a0bd29297be3ea (diff)
parent76aaf17794c37cb134fc968d04e1982958af12fd (diff)
downloadrust-d5366b5c19c28270dfcce4cb15c90fc7cf194a60.tar.gz
rust-d5366b5c19c28270dfcce4cb15c90fc7cf194a60.zip
Auto merge of #16265 - Patryk27:suggest-pub-crate-imports, r=Veykril
fix: Acknowledge `pub(crate)` imports in import suggestions

rust-analyzer has logic that discounts suggesting `use`s for private imports, but that logic is unnecessarily strict - for instance given this code:

```rust
mod foo {
    pub struct Foo;
}

pub(crate) use self::foo::*;

mod bar {
    fn main() {
        Foo$0;
    }
}
```

... RA will suggest to add `use crate::foo::Foo;`, which not only makes the code overly verbose (especially in larger code bases), but also is disjoint with what rustc itself suggests.

This commit adjusts the logic, so that `pub(crate)` imports are taken into account when generating the suggestions; considering rustc's behavior, I think this change doesn't warrant any extra configuration flag.

Note that this is my first commit to RA, so I guess the approach taken here might be suboptimal - certainly feels somewhat hacky, maybe there's some better way of finding out the optimal import path 😅
Diffstat (limited to 'crates/hir-def/src/find_path.rs')
-rw-r--r--crates/hir-def/src/find_path.rs31
1 files changed, 30 insertions, 1 deletions
diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs
index 4737b48703d..e8086be86f4 100644
--- a/crates/hir-def/src/find_path.rs
+++ b/crates/hir-def/src/find_path.rs
@@ -551,7 +551,18 @@ fn find_local_import_locations(
         if let Some((name, vis)) = data.scope.name_of(item) {
             if vis.is_visible_from(db, from) {
                 let is_private = match vis {
-                    Visibility::Module(private_to) => private_to.local_id == module.local_id,
+                    Visibility::Module(private_mod, private_vis) => {
+                        if private_mod == def_map.module_id(DefMap::ROOT)
+                            && private_vis.is_explicit()
+                        {
+                            // Treat `pub(crate)` imports as non-private, so
+                            // that we suggest adding `use crate::Foo;` instead
+                            // of `use crate::foo::Foo;` etc.
+                            false
+                        } else {
+                            private_mod.local_id == module.local_id
+                        }
+                    }
                     Visibility::Public => false,
                 };
                 let is_original_def = match item.as_module_def_id() {
@@ -1022,6 +1033,24 @@ $0
     }
 
     #[test]
+    fn promote_pub_crate_imports() {
+        check_found_path(
+            r#"
+//- /main.rs
+mod foo;
+pub mod bar { pub struct S; }
+pub(crate) use bar::S;
+//- /foo.rs
+$0
+        "#,
+            "crate::S",
+            "crate::S",
+            "crate::S",
+            "crate::S",
+        );
+    }
+
+    #[test]
     fn import_cycle() {
         check_found_path(
             r#"