Add doc(alias)-based field completion

This commit is contained in:
hecatia-elegua 2023-04-05 19:28:55 +02:00
parent da9c0bd0a7
commit 410acd7188
5 changed files with 40 additions and 13 deletions

View File

@ -430,8 +430,9 @@ pub(crate) fn add_field(
Visible::Editable => true, Visible::Editable => true,
Visible::No => return, Visible::No => return,
}; };
let doc_aliases = ctx.doc_aliases(&field);
let item = render_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, dot_access,
receiver, receiver,
field, field,

View File

@ -441,6 +441,14 @@ pub(crate) fn is_visible<I>(&self, item: &I) -> Visible
self.is_visible_impl(&vis, &attrs, item.krate(self.db)) 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)]`. /// Check if an item is `#[doc(hidden)]`.
pub(crate) fn is_item_hidden(&self, item: &hir::ItemInNs) -> bool { pub(crate) fn is_item_hidden(&self, item: &hir::ItemInNs) -> bool {
let attrs = item.attrs(self.db); let attrs = item.attrs(self.db);
@ -499,7 +507,7 @@ pub(crate) fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef, Vec<Smo
if self.is_scope_def_hidden(def) { if self.is_scope_def_hidden(def) {
return; return;
} }
let doc_aliases = self.doc_aliases(def); let doc_aliases = self.doc_aliases_in_scope(def);
f(name, def, doc_aliases); f(name, def, doc_aliases);
}); });
} }
@ -547,7 +555,7 @@ fn is_doc_hidden(&self, attrs: &hir::Attrs, defining_crate: hir::Crate) -> bool
self.krate != defining_crate && attrs.has_doc_hidden() self.krate != defining_crate && attrs.has_doc_hidden()
} }
fn doc_aliases(&self, scope_def: ScopeDef) -> Vec<SmolStr> { fn doc_aliases_in_scope(&self, scope_def: ScopeDef) -> Vec<SmolStr> {
if let Some(attrs) = scope_def.attrs(self.db) { if let Some(attrs) = scope_def.attrs(self.db) {
attrs.doc_aliases().collect() attrs.doc_aliases().collect()
} else { } else {

View File

@ -4,6 +4,7 @@
use hir::{Documentation, Mutability}; use hir::{Documentation, Mutability};
use ide_db::{imports::import_assets::LocatedImport, SnippetCap, SymbolKind}; use ide_db::{imports::import_assets::LocatedImport, SnippetCap, SymbolKind};
use itertools::Itertools;
use smallvec::SmallVec; use smallvec::SmallVec;
use stdx::{impl_from, never}; use stdx::{impl_from, never};
use syntax::{SmolStr, TextRange, TextSize}; use syntax::{SmolStr, TextRange, TextSize};
@ -353,7 +354,7 @@ pub(crate) fn new(
relevance: CompletionRelevance::default(), relevance: CompletionRelevance::default(),
ref_match: None, ref_match: None,
imports_to_add: Default::default(), imports_to_add: Default::default(),
doc_aliases: None, doc_aliases: vec![],
} }
} }
@ -386,7 +387,7 @@ pub(crate) struct Builder {
source_range: TextRange, source_range: TextRange,
imports_to_add: SmallVec<[LocatedImport; 1]>, imports_to_add: SmallVec<[LocatedImport; 1]>,
trait_name: Option<SmolStr>, trait_name: Option<SmolStr>,
doc_aliases: Option<SmolStr>, doc_aliases: Vec<SmolStr>,
label: SmolStr, label: SmolStr,
insert_text: Option<String>, insert_text: Option<String>,
is_snippet: bool, is_snippet: bool,
@ -418,7 +419,8 @@ pub(crate) fn build(self) -> CompletionItem {
let mut lookup = self.lookup.unwrap_or_else(|| label.clone()); let mut lookup = self.lookup.unwrap_or_else(|| label.clone());
let insert_text = self.insert_text.unwrap_or_else(|| label.to_string()); 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})")); label = SmolStr::from(format!("{label} (alias {doc_aliases})"));
lookup = SmolStr::from(format!("{lookup} {doc_aliases}")); lookup = SmolStr::from(format!("{lookup} {doc_aliases}"));
} }
@ -464,8 +466,8 @@ pub(crate) fn trait_name(&mut self, trait_name: SmolStr) -> &mut Builder {
self.trait_name = Some(trait_name); self.trait_name = Some(trait_name);
self self
} }
pub(crate) fn doc_aliases(&mut self, doc_aliases: SmolStr) -> &mut Builder { pub(crate) fn doc_aliases(&mut self, doc_aliases: Vec<SmolStr>) -> &mut Builder {
self.doc_aliases = Some(doc_aliases); self.doc_aliases = doc_aliases;
self self
} }
pub(crate) fn insert_text(&mut self, insert_text: impl Into<String>) -> &mut Builder { pub(crate) fn insert_text(&mut self, insert_text: impl Into<String>) -> &mut Builder {

View File

@ -152,6 +152,7 @@ pub(crate) fn render_field(
} }
} }
} }
item.doc_aliases(ctx.doc_aliases);
item.build() item.build()
} }
@ -361,11 +362,7 @@ fn render_resolution_simple_(
item.add_import(import_to_add); item.add_import(import_to_add);
} }
let doc_aliases = ctx.doc_aliases; item.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 item
} }

View File

@ -1086,3 +1086,22 @@ fn here_we_go() fn()
"#]], "#]],
); );
} }
#[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
"#]],
);
}