Unnamed repository; edit this file 'description' to name the repository.
-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 6f23bc5c74..bc7a94cd33 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 70c91e6a10..9daa6984c3 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 49f97d7a4c..1edf636aea 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 d99414fe35..7b145f3c14 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 c2c4a663c6..e95cae9d67 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 514a684726..9673252ff5 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 197592e78c..bfcd23280c 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 1749e8e70f..e23f3ae72e 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
+ "#]],
+ );
+}