about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-04-24 06:34:25 +0000
committerbors <bors@rust-lang.org>2023-04-24 06:34:25 +0000
commit420a038da9ea6d809c3c97491eb47f61b8afdae9 (patch)
treeeb4f1b74fdf4178799ae3118dfd621b9b0bf38f7
parentb2e6f3a9da790fd449e28d41f77508ea13164466 (diff)
parent398af0259f7614ff8a0d603edd5d94ce9aecd5f2 (diff)
downloadrust-420a038da9ea6d809c3c97491eb47f61b8afdae9.tar.gz
rust-420a038da9ea6d809c3c97491eb47f61b8afdae9.zip
Auto merge of #14513 - hecatia-elegua:alias-based-completion2, r=Veykril
doc(alias)-based completion round 2

Follow-up on #14433
We can now complete fields, functions and some use/mods.
Flyimports don't behave, I don't really have the time to understand the structure there either.
While reading the flyimport code, I removed one method only used there, the closure-tree was a bit confusing, I can revert that if you want.
-rw-r--r--crates/ide-completion/src/completions.rs11
-rw-r--r--crates/ide-completion/src/completions/expr.rs8
-rw-r--r--crates/ide-completion/src/completions/flyimport.rs88
-rw-r--r--crates/ide-completion/src/context.rs12
-rw-r--r--crates/ide-completion/src/item.rs20
-rw-r--r--crates/ide-completion/src/render.rs12
-rw-r--r--crates/ide-completion/src/render/function.rs2
-rw-r--r--crates/ide-completion/src/tests/special.rs138
8 files changed, 214 insertions, 77 deletions
diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs
index 6f23bc5c747..bc7a94cd337 100644
--- a/crates/ide-completion/src/completions.rs
+++ b/crates/ide-completion/src/completions.rs
@@ -78,14 +78,6 @@ impl Completions {
         }
     }
 
-    pub(crate) fn add_all<I>(&mut self, items: I)
-    where
-        I: IntoIterator,
-        I::Item: Into<CompletionItem>,
-    {
-        items.into_iter().for_each(|item| self.add(item.into()))
-    }
-
     pub(crate) fn add_keyword(&mut self, ctx: &CompletionContext<'_>, keyword: &'static str) {
         let item = CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), keyword);
         item.add_to(self);
@@ -472,8 +464,9 @@ impl Completions {
             Visible::Editable => true,
             Visible::No => return,
         };
+        let doc_aliases = ctx.doc_aliases(&field);
         let item = render_field(
-            RenderContext::new(ctx).private_editable(is_private_editable),
+            RenderContext::new(ctx).private_editable(is_private_editable).doc_aliases(doc_aliases),
             dot_access,
             receiver,
             field,
diff --git a/crates/ide-completion/src/completions/expr.rs b/crates/ide-completion/src/completions/expr.rs
index 70c91e6a102..9daa6984c3e 100644
--- a/crates/ide-completion/src/completions/expr.rs
+++ b/crates/ide-completion/src/completions/expr.rs
@@ -88,7 +88,13 @@ pub(crate) fn complete_expr_path(
                     let module_scope = module.scope(ctx.db, Some(ctx.module));
                     for (name, def) in module_scope {
                         if scope_def_applicable(def) {
-                            acc.add_path_resolution(ctx, path_ctx, name, def, vec![]);
+                            acc.add_path_resolution(
+                                ctx,
+                                path_ctx,
+                                name,
+                                def,
+                                ctx.doc_aliases_in_scope(def),
+                            );
                         }
                     }
                 }
diff --git a/crates/ide-completion/src/completions/flyimport.rs b/crates/ide-completion/src/completions/flyimport.rs
index 49f97d7a4ce..1edf636aea0 100644
--- a/crates/ide-completion/src/completions/flyimport.rs
+++ b/crates/ide-completion/src/completions/flyimport.rs
@@ -257,32 +257,24 @@ fn import_on_the_fly(
     };
     let user_input_lowercased = potential_import_name.to_lowercase();
 
-    acc.add_all(
-        import_assets
-            .search_for_imports(
-                &ctx.sema,
-                ctx.config.insert_use.prefix_kind,
-                ctx.config.prefer_no_std,
-            )
-            .into_iter()
-            .filter(ns_filter)
-            .filter(|import| {
-                let original_item = &import.original_item;
-                !ctx.is_item_hidden(&import.item_to_import)
-                    && !ctx.is_item_hidden(original_item)
-                    && ctx.check_stability(original_item.attrs(ctx.db).as_deref())
-            })
-            .sorted_by_key(|located_import| {
-                compute_fuzzy_completion_order_key(
-                    &located_import.import_path,
-                    &user_input_lowercased,
-                )
-            })
-            .filter_map(|import| {
-                render_resolution_with_import(RenderContext::new(ctx), path_ctx, import)
-            })
-            .map(|builder| builder.build()),
-    );
+    import_assets
+        .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind, ctx.config.prefer_no_std)
+        .into_iter()
+        .filter(ns_filter)
+        .filter(|import| {
+            let original_item = &import.original_item;
+            !ctx.is_item_hidden(&import.item_to_import)
+                && !ctx.is_item_hidden(original_item)
+                && ctx.check_stability(original_item.attrs(ctx.db).as_deref())
+        })
+        .sorted_by_key(|located_import| {
+            compute_fuzzy_completion_order_key(&located_import.import_path, &user_input_lowercased)
+        })
+        .filter_map(|import| {
+            render_resolution_with_import(RenderContext::new(ctx), path_ctx, import)
+        })
+        .map(|builder| builder.build())
+        .for_each(|item| acc.add(item));
     Some(())
 }
 
@@ -307,32 +299,24 @@ fn import_on_the_fly_pat_(
     };
     let user_input_lowercased = potential_import_name.to_lowercase();
 
-    acc.add_all(
-        import_assets
-            .search_for_imports(
-                &ctx.sema,
-                ctx.config.insert_use.prefix_kind,
-                ctx.config.prefer_no_std,
-            )
-            .into_iter()
-            .filter(ns_filter)
-            .filter(|import| {
-                let original_item = &import.original_item;
-                !ctx.is_item_hidden(&import.item_to_import)
-                    && !ctx.is_item_hidden(original_item)
-                    && ctx.check_stability(original_item.attrs(ctx.db).as_deref())
-            })
-            .sorted_by_key(|located_import| {
-                compute_fuzzy_completion_order_key(
-                    &located_import.import_path,
-                    &user_input_lowercased,
-                )
-            })
-            .filter_map(|import| {
-                render_resolution_with_import_pat(RenderContext::new(ctx), pattern_ctx, import)
-            })
-            .map(|builder| builder.build()),
-    );
+    import_assets
+        .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind, ctx.config.prefer_no_std)
+        .into_iter()
+        .filter(ns_filter)
+        .filter(|import| {
+            let original_item = &import.original_item;
+            !ctx.is_item_hidden(&import.item_to_import)
+                && !ctx.is_item_hidden(original_item)
+                && ctx.check_stability(original_item.attrs(ctx.db).as_deref())
+        })
+        .sorted_by_key(|located_import| {
+            compute_fuzzy_completion_order_key(&located_import.import_path, &user_input_lowercased)
+        })
+        .filter_map(|import| {
+            render_resolution_with_import_pat(RenderContext::new(ctx), pattern_ctx, import)
+        })
+        .map(|builder| builder.build())
+        .for_each(|item| acc.add(item));
     Some(())
 }
 
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index d99414fe358..7b145f3c14e 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -443,6 +443,14 @@ impl CompletionContext<'_> {
         self.is_visible_impl(&vis, &attrs, item.krate(self.db))
     }
 
+    pub(crate) fn doc_aliases<I>(&self, item: &I) -> Vec<SmolStr>
+    where
+        I: hir::HasAttrs + Copy,
+    {
+        let attrs = item.attrs(self.db);
+        attrs.doc_aliases().collect()
+    }
+
     /// Check if an item is `#[doc(hidden)]`.
     pub(crate) fn is_item_hidden(&self, item: &hir::ItemInNs) -> bool {
         let attrs = item.attrs(self.db);
@@ -507,7 +515,7 @@ impl CompletionContext<'_> {
             if self.is_scope_def_hidden(def) {
                 return;
             }
-            let doc_aliases = self.doc_aliases(def);
+            let doc_aliases = self.doc_aliases_in_scope(def);
             f(name, def, doc_aliases);
         });
     }
@@ -555,7 +563,7 @@ impl CompletionContext<'_> {
         self.krate != defining_crate && attrs.has_doc_hidden()
     }
 
-    fn doc_aliases(&self, scope_def: ScopeDef) -> Vec<SmolStr> {
+    pub(crate) fn doc_aliases_in_scope(&self, scope_def: ScopeDef) -> Vec<SmolStr> {
         if let Some(attrs) = scope_def.attrs(self.db) {
             attrs.doc_aliases().collect()
         } else {
diff --git a/crates/ide-completion/src/item.rs b/crates/ide-completion/src/item.rs
index c2c4a663c61..e95cae9d67f 100644
--- a/crates/ide-completion/src/item.rs
+++ b/crates/ide-completion/src/item.rs
@@ -4,6 +4,7 @@ use std::fmt;
 
 use hir::{Documentation, Mutability};
 use ide_db::{imports::import_assets::LocatedImport, SnippetCap, SymbolKind};
+use itertools::Itertools;
 use smallvec::SmallVec;
 use stdx::{impl_from, never};
 use syntax::{SmolStr, TextRange, TextSize};
@@ -353,7 +354,7 @@ impl CompletionItem {
             relevance: CompletionRelevance::default(),
             ref_match: None,
             imports_to_add: Default::default(),
-            doc_aliases: None,
+            doc_aliases: vec![],
         }
     }
 
@@ -386,7 +387,7 @@ pub(crate) struct Builder {
     source_range: TextRange,
     imports_to_add: SmallVec<[LocatedImport; 1]>,
     trait_name: Option<SmolStr>,
-    doc_aliases: Option<SmolStr>,
+    doc_aliases: Vec<SmolStr>,
     label: SmolStr,
     insert_text: Option<String>,
     is_snippet: bool,
@@ -408,7 +409,13 @@ impl Builder {
         local_name: hir::Name,
         resolution: hir::ScopeDef,
     ) -> Self {
-        render_path_resolution(RenderContext::new(ctx), path_ctx, local_name, resolution)
+        let doc_aliases = ctx.doc_aliases_in_scope(resolution);
+        render_path_resolution(
+            RenderContext::new(ctx).doc_aliases(doc_aliases),
+            path_ctx,
+            local_name,
+            resolution,
+        )
     }
 
     pub(crate) fn build(self) -> CompletionItem {
@@ -418,7 +425,8 @@ impl Builder {
         let mut lookup = self.lookup.unwrap_or_else(|| label.clone());
         let insert_text = self.insert_text.unwrap_or_else(|| label.to_string());
 
-        if let Some(doc_aliases) = self.doc_aliases {
+        if !self.doc_aliases.is_empty() {
+            let doc_aliases = self.doc_aliases.into_iter().join(", ");
             label = SmolStr::from(format!("{label} (alias {doc_aliases})"));
             lookup = SmolStr::from(format!("{lookup} {doc_aliases}"));
         }
@@ -464,8 +472,8 @@ impl Builder {
         self.trait_name = Some(trait_name);
         self
     }
-    pub(crate) fn doc_aliases(&mut self, doc_aliases: SmolStr) -> &mut Builder {
-        self.doc_aliases = Some(doc_aliases);
+    pub(crate) fn doc_aliases(&mut self, doc_aliases: Vec<SmolStr>) -> &mut Builder {
+        self.doc_aliases = doc_aliases;
         self
     }
     pub(crate) fn insert_text(&mut self, insert_text: impl Into<String>) -> &mut Builder {
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index 514a6847266..9673252ff52 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -14,7 +14,6 @@ use hir::{AsAssocItem, HasAttrs, HirDisplay, ScopeDef};
 use ide_db::{
     helpers::item_name, imports::import_assets::LocatedImport, RootDatabase, SnippetCap, SymbolKind,
 };
-use itertools::Itertools;
 use syntax::{AstNode, SmolStr, SyntaxKind, TextRange};
 
 use crate::{
@@ -152,6 +151,7 @@ pub(crate) fn render_field(
             }
         }
     }
+    item.doc_aliases(ctx.doc_aliases);
     item.build()
 }
 
@@ -209,7 +209,9 @@ pub(crate) fn render_resolution_with_import(
 ) -> Option<Builder> {
     let resolution = ScopeDef::from(import_edit.original_item);
     let local_name = scope_def_to_name(resolution, &ctx, &import_edit)?;
-
+    //this now just renders the alias text, but we need to find the aliases earlier and call this with the alias instead
+    let doc_aliases = ctx.completion.doc_aliases_in_scope(resolution);
+    let ctx = ctx.doc_aliases(doc_aliases);
     Some(render_resolution_path(ctx, path_ctx, local_name, Some(import_edit), resolution))
 }
 
@@ -361,11 +363,7 @@ fn render_resolution_simple_(
         item.add_import(import_to_add);
     }
 
-    let doc_aliases = ctx.doc_aliases;
-    if !doc_aliases.is_empty() {
-        let doc_aliases = doc_aliases.into_iter().join(", ").into();
-        item.doc_aliases(doc_aliases);
-    }
+    item.doc_aliases(ctx.doc_aliases);
     item
 }
 
diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs
index 197592e78ce..bfcd23280ce 100644
--- a/crates/ide-completion/src/render/function.rs
+++ b/crates/ide-completion/src/render/function.rs
@@ -147,6 +147,8 @@ fn render(
             }
         }
     }
+
+    item.doc_aliases(ctx.doc_aliases);
     item
 }
 
diff --git a/crates/ide-completion/src/tests/special.rs b/crates/ide-completion/src/tests/special.rs
index 1749e8e70f8..e23f3ae72eb 100644
--- a/crates/ide-completion/src/tests/special.rs
+++ b/crates/ide-completion/src/tests/special.rs
@@ -1086,3 +1086,141 @@ fn here_we_go() {
         "#]],
     );
 }
+
+#[test]
+fn completes_field_name_via_doc_alias_in_fn_body() {
+    check(
+        r#"
+struct Foo {
+    #[doc(alias = "qux")]
+    bar: u8
+};
+
+fn here_we_go() {
+    let foo = Foo { q$0 }
+}
+"#,
+        expect![[r#"
+            fd bar (alias qux) u8
+        "#]],
+    );
+}
+
+#[test]
+fn completes_fn_name_via_doc_alias_in_fn_body() {
+    check(
+        r#"
+#[doc(alias = "qux")]
+fn foo() {}
+fn bar() { qu$0 }
+"#,
+        expect![[r#"
+            fn bar()             fn()
+            fn foo() (alias qux) fn()
+            bt u32
+            kw const
+            kw crate::
+            kw enum
+            kw extern
+            kw false
+            kw fn
+            kw for
+            kw if
+            kw if let
+            kw impl
+            kw let
+            kw loop
+            kw match
+            kw mod
+            kw return
+            kw self::
+            kw static
+            kw struct
+            kw trait
+            kw true
+            kw type
+            kw union
+            kw unsafe
+            kw use
+            kw while
+            kw while let
+            sn macro_rules
+            sn pd
+            sn ppd
+        "#]],
+    );
+}
+
+#[test]
+fn completes_struct_name_via_doc_alias_in_another_mod() {
+    check(
+        r#"
+mod foo {
+    #[doc(alias = "Qux")]
+    pub struct Bar(u8);
+}
+
+fn here_we_go() {
+    use foo;
+    let foo = foo::Q$0
+}
+"#,
+        expect![[r#"
+            st Bar (alias Qux)
+        "#]],
+    );
+}
+
+#[test]
+fn completes_use_via_doc_alias_in_another_mod() {
+    check(
+        r#"
+mod foo {
+    #[doc(alias = "Qux")]
+    pub struct Bar(u8);
+}
+
+fn here_we_go() {
+    use foo::Q$0;
+}
+"#,
+        expect![[r#"
+            st Bar (alias Qux)
+        "#]],
+    );
+}
+
+#[test]
+fn completes_flyimport_with_doc_alias_in_another_mod() {
+    check(
+        r#"
+mod foo {
+    #[doc(alias = "Qux")]
+    pub struct Bar();
+}
+
+fn here_we_go() {
+    let foo = Bar$0
+}
+"#,
+        expect![[r#"
+            fn here_we_go()           fn()
+            md foo
+            st Bar (alias Qux) (use foo::Bar)
+            bt u32
+            kw crate::
+            kw false
+            kw for
+            kw if
+            kw if let
+            kw loop
+            kw match
+            kw return
+            kw self::
+            kw true
+            kw unsafe
+            kw while
+            kw while let
+        "#]],
+    );
+}