Unnamed repository; edit this file 'description' to name the repository.
Merge #11086
11086: internal: Simplify completion rendering r=Veykril a=Veykril Removes all the helper render structs in favor of simple functions, making things a lot easier to oversee(imho) bors r+ Co-authored-by: Lukas Wirth <[email protected]>
bors[bot] 2021-12-21
parent a406574 · parent 929cae7 · commit 22adcfd
-rw-r--r--crates/hir/src/lib.rs2
-rw-r--r--crates/ide_completion/src/completions.rs6
-rw-r--r--crates/ide_completion/src/completions/lifetime.rs4
-rw-r--r--crates/ide_completion/src/completions/pattern.rs2
-rw-r--r--crates/ide_completion/src/completions/qualified_path.rs8
-rw-r--r--crates/ide_completion/src/completions/unqualified_path.rs10
-rw-r--r--crates/ide_completion/src/context.rs6
-rw-r--r--crates/ide_completion/src/render.rs132
-rw-r--r--crates/ide_completion/src/render/const_.rs57
-rw-r--r--crates/ide_completion/src/render/enum_variant.rs172
-rw-r--r--crates/ide_completion/src/render/function.rs219
-rw-r--r--crates/ide_completion/src/render/macro_.rs150
-rw-r--r--crates/ide_completion/src/render/type_alias.rs78
-rw-r--r--crates/ide_completion/src/tests/use_tree.rs2
14 files changed, 383 insertions, 465 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index b57f49690a..526e90bd0b 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -3024,7 +3024,7 @@ impl Callable {
}
/// For IDE only
-#[derive(Debug, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum ScopeDef {
ModuleDef(ModuleDef),
MacroDef(MacroDef),
diff --git a/crates/ide_completion/src/completions.rs b/crates/ide_completion/src/completions.rs
index 8474ebec0d..974264c319 100644
--- a/crates/ide_completion/src/completions.rs
+++ b/crates/ide_completion/src/completions.rs
@@ -84,7 +84,7 @@ impl Completions {
&mut self,
ctx: &CompletionContext,
local_name: hir::Name,
- resolution: &hir::ScopeDef,
+ resolution: hir::ScopeDef,
) {
if ctx.is_scope_def_hidden(resolution) {
cov_mark::hit!(qualified_path_doc_hidden);
@@ -115,7 +115,7 @@ impl Completions {
if !ctx.is_visible(&func) {
return;
}
- self.add_opt(render_fn(RenderContext::new(ctx), None, local_name, func));
+ self.add(render_fn(RenderContext::new(ctx), None, local_name, func));
}
pub(crate) fn add_method(
@@ -128,7 +128,7 @@ impl Completions {
if !ctx.is_visible(&func) {
return;
}
- self.add_opt(render_method(RenderContext::new(ctx), None, receiver, local_name, func));
+ self.add(render_method(RenderContext::new(ctx), None, receiver, local_name, func));
}
pub(crate) fn add_const(&mut self, ctx: &CompletionContext, konst: hir::Const) {
diff --git a/crates/ide_completion/src/completions/lifetime.rs b/crates/ide_completion/src/completions/lifetime.rs
index f530825434..4082414f02 100644
--- a/crates/ide_completion/src/completions/lifetime.rs
+++ b/crates/ide_completion/src/completions/lifetime.rs
@@ -35,7 +35,7 @@ pub(crate) fn complete_lifetime(acc: &mut Completions, ctx: &CompletionContext)
ctx.scope.process_all_names(&mut |name, res| {
if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res {
if param_lifetime != Some(&*name.to_smol_str()) {
- acc.add_resolution(ctx, name, &res);
+ acc.add_resolution(ctx, name, res);
}
}
});
@@ -51,7 +51,7 @@ pub(crate) fn complete_label(acc: &mut Completions, ctx: &CompletionContext) {
}
ctx.scope.process_all_names(&mut |name, res| {
if let ScopeDef::Label(_) = res {
- acc.add_resolution(ctx, name, &res);
+ acc.add_resolution(ctx, name, res);
}
});
}
diff --git a/crates/ide_completion/src/completions/pattern.rs b/crates/ide_completion/src/completions/pattern.rs
index b3b27f251f..a140ca4239 100644
--- a/crates/ide_completion/src/completions/pattern.rs
+++ b/crates/ide_completion/src/completions/pattern.rs
@@ -59,7 +59,7 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
_ => false,
};
if add_resolution {
- acc.add_resolution(ctx, name, &res);
+ acc.add_resolution(ctx, name, res);
}
});
}
diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs
index a0d6d5cdc6..656d46b10b 100644
--- a/crates/ide_completion/src/completions/qualified_path.rs
+++ b/crates/ide_completion/src/completions/qualified_path.rs
@@ -44,7 +44,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
}
}
if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = def {
- acc.add_resolution(ctx, name, &def);
+ acc.add_resolution(ctx, name, def);
}
}
}
@@ -64,7 +64,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
.next()
{
if let Some(name) = next.name(ctx.db) {
- acc.add_resolution(ctx, name, &ScopeDef::ModuleDef(next.into()));
+ acc.add_resolution(ctx, name, ScopeDef::ModuleDef(next.into()));
}
}
}
@@ -80,7 +80,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
_ => false,
};
if add_resolution {
- acc.add_resolution(ctx, name, &def);
+ acc.add_resolution(ctx, name, def);
}
}
}
@@ -147,7 +147,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
};
if add_resolution {
- acc.add_resolution(ctx, name, &def);
+ acc.add_resolution(ctx, name, def);
}
}
}
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs
index ac1ba2da7c..e7980c12d7 100644
--- a/crates/ide_completion/src/completions/unqualified_path.rs
+++ b/crates/ide_completion/src/completions/unqualified_path.rs
@@ -24,7 +24,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
cov_mark::hit!(unqualified_path_only_modules_in_import);
ctx.process_all_names(&mut |name, res| {
if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
- acc.add_resolution(ctx, name, &res);
+ acc.add_resolution(ctx, name, res);
}
});
@@ -43,7 +43,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
_ => false,
};
if add_resolution {
- acc.add_resolution(ctx, name, &res);
+ acc.add_resolution(ctx, name, res);
}
});
return;
@@ -61,7 +61,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
}
}
if let hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
- acc.add_resolution(ctx, name, &res);
+ acc.add_resolution(ctx, name, res);
}
});
return;
@@ -76,7 +76,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
_ => false,
};
if add_resolution {
- acc.add_resolution(ctx, name, &res);
+ acc.add_resolution(ctx, name, res);
}
});
return;
@@ -134,7 +134,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
_ => true,
};
if add_resolution {
- acc.add_resolution(ctx, name, &res);
+ acc.add_resolution(ctx, name, res);
}
});
}
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index c6af285e86..d0ed988989 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -278,7 +278,7 @@ impl<'a> CompletionContext<'a> {
self.is_visible_impl(&item.visibility(self.db), &item.attrs(self.db), item.krate(self.db))
}
- pub(crate) fn is_scope_def_hidden(&self, scope_def: &ScopeDef) -> bool {
+ pub(crate) fn is_scope_def_hidden(&self, scope_def: ScopeDef) -> bool {
if let (Some(attrs), Some(krate)) = (scope_def.attrs(self.db), scope_def.krate(self.db)) {
return self.is_doc_hidden(&attrs, krate);
}
@@ -303,7 +303,7 @@ impl<'a> CompletionContext<'a> {
/// A version of [`SemanticsScope::process_all_names`] that filters out `#[doc(hidden)]` items.
pub(crate) fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef)) {
self.scope.process_all_names(&mut |name, def| {
- if self.is_scope_def_hidden(&def) {
+ if self.is_scope_def_hidden(def) {
return;
}
@@ -367,7 +367,7 @@ impl<'a> CompletionContext<'a> {
parse.reparse(&edit).tree()
};
let fake_ident_token =
- file_with_fake_ident.syntax().token_at_offset(offset).right_biased().unwrap();
+ file_with_fake_ident.syntax().token_at_offset(offset).right_biased()?;
let original_token = original_file.syntax().token_at_offset(offset).left_biased()?;
let token = sema.descend_into_macros_single(original_token.clone());
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs
index 4b4fbb3ed9..404a2fa9d3 100644
--- a/crates/ide_completion/src/render.rs
+++ b/crates/ide_completion/src/render.rs
@@ -11,7 +11,7 @@ pub(crate) mod struct_literal;
mod builder_ext;
-use hir::{AsAssocItem, HasAttrs, HirDisplay};
+use hir::{AsAssocItem, HasAttrs, HirDisplay, ScopeDef};
use ide_db::{
helpers::{item_name, SnippetCap},
RootDatabase, SymbolKind,
@@ -47,8 +47,8 @@ impl<'a> RenderContext<'a> {
self.completion.source_range()
}
- fn is_deprecated(&self, node: impl HasAttrs) -> bool {
- let attrs = node.attrs(self.db());
+ fn is_deprecated(&self, def: impl HasAttrs) -> bool {
+ let attrs = def.attrs(self.db());
attrs.by_key("deprecated").exists() || attrs.by_key("rustc_deprecated").exists()
}
@@ -71,8 +71,8 @@ impl<'a> RenderContext<'a> {
.unwrap_or(false)
}
- fn docs(&self, node: impl HasAttrs) -> Option<hir::Documentation> {
- node.docs(self.db())
+ fn docs(&self, def: impl HasAttrs) -> Option<hir::Documentation> {
+ def.docs(self.db())
}
}
@@ -128,7 +128,7 @@ pub(crate) fn render_tuple_field(
pub(crate) fn render_resolution(
ctx: RenderContext<'_>,
local_name: hir::Name,
- resolution: &hir::ScopeDef,
+ resolution: ScopeDef,
) -> Option<CompletionItem> {
render_resolution_(ctx, local_name, None, resolution)
}
@@ -137,83 +137,77 @@ pub(crate) fn render_resolution_with_import(
ctx: RenderContext<'_>,
import_edit: ImportEdit,
) -> Option<CompletionItem> {
- let resolution = hir::ScopeDef::from(import_edit.import.original_item);
+ let resolution = ScopeDef::from(import_edit.import.original_item);
let local_name = match resolution {
- hir::ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db),
- hir::ScopeDef::ModuleDef(hir::ModuleDef::Const(c)) => c.name(ctx.completion.db)?,
- hir::ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db),
+ ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db),
+ ScopeDef::ModuleDef(hir::ModuleDef::Const(c)) => c.name(ctx.completion.db)?,
+ ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db),
_ => item_name(ctx.db(), import_edit.import.original_item)?,
};
- render_resolution_(ctx, local_name, Some(import_edit), &resolution)
+ render_resolution_(ctx, local_name, Some(import_edit), resolution)
}
fn render_resolution_(
ctx: RenderContext<'_>,
local_name: hir::Name,
import_to_add: Option<ImportEdit>,
- resolution: &hir::ScopeDef,
+ resolution: ScopeDef,
) -> Option<CompletionItem> {
let _p = profile::span("render_resolution");
use hir::ModuleDef::*;
+ let db = ctx.db();
+
let kind = match resolution {
- hir::ScopeDef::ModuleDef(Function(func)) => {
- return render_fn(ctx, import_to_add, Some(local_name), *func);
- }
- hir::ScopeDef::ModuleDef(Variant(_)) if ctx.completion.pattern_ctx.is_some() => {
- CompletionItemKind::SymbolKind(SymbolKind::Variant)
+ ScopeDef::ModuleDef(Function(func)) => {
+ return Some(render_fn(ctx, import_to_add, Some(local_name), func));
}
- hir::ScopeDef::ModuleDef(Variant(var)) => {
- let item = render_variant(ctx, import_to_add, Some(local_name), *var, None);
- return Some(item);
+ ScopeDef::ModuleDef(Variant(var)) if ctx.completion.pattern_ctx.is_none() => {
+ return Some(render_variant(ctx, import_to_add, Some(local_name), var, None));
}
- hir::ScopeDef::MacroDef(mac) => {
- let item = render_macro(ctx, import_to_add, local_name, *mac);
- return item;
+ ScopeDef::MacroDef(mac) => return render_macro(ctx, import_to_add, local_name, mac),
+ ScopeDef::Unknown => {
+ let mut item = CompletionItem::new(
+ CompletionItemKind::UnresolvedReference,
+ ctx.source_range(),
+ local_name.to_smol_str(),
+ );
+ if let Some(import_to_add) = import_to_add {
+ item.add_import(import_to_add);
+ }
+ return Some(item.build());
}
- hir::ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::SymbolKind(SymbolKind::Module),
- hir::ScopeDef::ModuleDef(Adt(adt)) => CompletionItemKind::SymbolKind(match adt {
+ ScopeDef::ModuleDef(Variant(_)) => CompletionItemKind::SymbolKind(SymbolKind::Variant),
+ ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::SymbolKind(SymbolKind::Module),
+ ScopeDef::ModuleDef(Adt(adt)) => CompletionItemKind::SymbolKind(match adt {
hir::Adt::Struct(_) => SymbolKind::Struct,
hir::Adt::Union(_) => SymbolKind::Union,
hir::Adt::Enum(_) => SymbolKind::Enum,
}),
- hir::ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::SymbolKind(SymbolKind::Const),
- hir::ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::SymbolKind(SymbolKind::Static),
- hir::ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::SymbolKind(SymbolKind::Trait),
- hir::ScopeDef::ModuleDef(TypeAlias(..)) => {
- CompletionItemKind::SymbolKind(SymbolKind::TypeAlias)
- }
- hir::ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType,
- hir::ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param {
+ ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::SymbolKind(SymbolKind::Const),
+ ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::SymbolKind(SymbolKind::Static),
+ ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::SymbolKind(SymbolKind::Trait),
+ ScopeDef::ModuleDef(TypeAlias(..)) => CompletionItemKind::SymbolKind(SymbolKind::TypeAlias),
+ ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType,
+ ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param {
hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam,
hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam,
hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam,
}),
- hir::ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local),
- hir::ScopeDef::Label(..) => CompletionItemKind::SymbolKind(SymbolKind::Label),
- hir::ScopeDef::AdtSelfType(..) | hir::ScopeDef::ImplSelfType(..) => {
+ ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local),
+ ScopeDef::Label(..) => CompletionItemKind::SymbolKind(SymbolKind::Label),
+ ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => {
CompletionItemKind::SymbolKind(SymbolKind::SelfParam)
}
- hir::ScopeDef::Unknown => {
- let mut item = CompletionItem::new(
- CompletionItemKind::UnresolvedReference,
- ctx.source_range(),
- local_name.to_smol_str(),
- );
- if let Some(import_to_add) = import_to_add {
- item.add_import(import_to_add);
- }
- return Some(item.build());
- }
};
let local_name = local_name.to_smol_str();
let mut item = CompletionItem::new(kind, ctx.source_range(), local_name.clone());
- if let hir::ScopeDef::Local(local) = resolution {
- let ty = local.ty(ctx.db());
+ if let ScopeDef::Local(local) = resolution {
+ let ty = local.ty(db);
if !ty.is_unknown() {
- item.detail(ty.display(ctx.db()).to_string());
+ item.detail(ty.display(db).to_string());
}
item.set_relevance(CompletionRelevance {
@@ -229,15 +223,15 @@ fn render_resolution_(
};
// Add `<>` for generic types
- if matches!(
+ let type_path_no_ty_args = matches!(
ctx.completion.path_context,
Some(PathCompletionContext { kind: Some(PathKind::Type), has_type_args: false, .. })
- ) && ctx.completion.config.add_call_parenthesis
- {
+ ) && ctx.completion.config.add_call_parenthesis;
+ if type_path_no_ty_args {
if let Some(cap) = ctx.snippet_cap() {
let has_non_default_type_params = match resolution {
- hir::ScopeDef::ModuleDef(Adt(it)) => it.has_non_default_type_params(ctx.db()),
- hir::ScopeDef::ModuleDef(TypeAlias(it)) => it.has_non_default_type_params(ctx.db()),
+ ScopeDef::ModuleDef(Adt(it)) => it.has_non_default_type_params(db),
+ ScopeDef::ModuleDef(TypeAlias(it)) => it.has_non_default_type_params(db),
_ => false,
};
if has_non_default_type_params {
@@ -248,7 +242,7 @@ fn render_resolution_(
}
}
}
- item.set_documentation(scope_def_docs(ctx.db(), resolution))
+ item.set_documentation(scope_def_docs(db, resolution))
.set_deprecated(scope_def_is_deprecated(&ctx, resolution));
if let Some(import_to_add) = import_to_add {
@@ -257,26 +251,26 @@ fn render_resolution_(
Some(item.build())
}
-fn scope_def_docs(db: &RootDatabase, resolution: &hir::ScopeDef) -> Option<hir::Documentation> {
+fn scope_def_docs(db: &RootDatabase, resolution: ScopeDef) -> Option<hir::Documentation> {
use hir::ModuleDef::*;
match resolution {
- hir::ScopeDef::ModuleDef(Module(it)) => it.docs(db),
- hir::ScopeDef::ModuleDef(Adt(it)) => it.docs(db),
- hir::ScopeDef::ModuleDef(Variant(it)) => it.docs(db),
- hir::ScopeDef::ModuleDef(Const(it)) => it.docs(db),
- hir::ScopeDef::ModuleDef(Static(it)) => it.docs(db),
- hir::ScopeDef::ModuleDef(Trait(it)) => it.docs(db),
- hir::ScopeDef::ModuleDef(TypeAlias(it)) => it.docs(db),
+ ScopeDef::ModuleDef(Module(it)) => it.docs(db),
+ ScopeDef::ModuleDef(Adt(it)) => it.docs(db),
+ ScopeDef::ModuleDef(Variant(it)) => it.docs(db),
+ ScopeDef::ModuleDef(Const(it)) => it.docs(db),
+ ScopeDef::ModuleDef(Static(it)) => it.docs(db),
+ ScopeDef::ModuleDef(Trait(it)) => it.docs(db),
+ ScopeDef::ModuleDef(TypeAlias(it)) => it.docs(db),
_ => None,
}
}
-fn scope_def_is_deprecated(ctx: &RenderContext<'_>, resolution: &hir::ScopeDef) -> bool {
+fn scope_def_is_deprecated(ctx: &RenderContext<'_>, resolution: ScopeDef) -> bool {
match resolution {
- hir::ScopeDef::ModuleDef(it) => ctx.is_deprecated_assoc_item(*it),
- hir::ScopeDef::MacroDef(it) => ctx.is_deprecated(*it),
- hir::ScopeDef::GenericParam(it) => ctx.is_deprecated(*it),
- hir::ScopeDef::AdtSelfType(it) => ctx.is_deprecated(*it),
+ ScopeDef::ModuleDef(it) => ctx.is_deprecated_assoc_item(it),
+ ScopeDef::MacroDef(it) => ctx.is_deprecated(it),
+ ScopeDef::GenericParam(it) => ctx.is_deprecated(it),
+ ScopeDef::AdtSelfType(it) => ctx.is_deprecated(it),
_ => false,
}
}
diff --git a/crates/ide_completion/src/render/const_.rs b/crates/ide_completion/src/render/const_.rs
index c40490ac0b..65c9d1d63e 100644
--- a/crates/ide_completion/src/render/const_.rs
+++ b/crates/ide_completion/src/render/const_.rs
@@ -2,53 +2,32 @@
use hir::{AsAssocItem, HasSource};
use ide_db::SymbolKind;
-use syntax::{ast::Const, display::const_label};
+use syntax::display::const_label;
use crate::{item::CompletionItem, render::RenderContext};
pub(crate) fn render_const(ctx: RenderContext<'_>, const_: hir::Const) -> Option<CompletionItem> {
let _p = profile::span("render_const");
- ConstRender::new(ctx, const_)?.render()
+ render(ctx, const_)
}
-#[derive(Debug)]
-struct ConstRender<'a> {
- ctx: RenderContext<'a>,
- const_: hir::Const,
- ast_node: Const,
-}
-
-impl<'a> ConstRender<'a> {
- fn new(ctx: RenderContext<'a>, const_: hir::Const) -> Option<ConstRender<'a>> {
- let ast_node = const_.source(ctx.db())?.value;
- Some(ConstRender { ctx, const_, ast_node })
- }
-
- fn render(self) -> Option<CompletionItem> {
- let name = self.const_.name(self.ctx.db())?.to_smol_str();
- let detail = self.detail();
-
- let mut item =
- CompletionItem::new(SymbolKind::Const, self.ctx.source_range(), name.clone());
- item.set_documentation(self.ctx.docs(self.const_))
- .set_deprecated(
- self.ctx.is_deprecated(self.const_)
- || self.ctx.is_deprecated_assoc_item(self.const_),
- )
- .detail(detail);
-
- let db = self.ctx.db();
- if let Some(actm) = self.const_.as_assoc_item(db) {
- if let Some(trt) = actm.containing_trait_or_trait_impl(db) {
- item.trait_name(trt.name(db).to_smol_str());
- item.insert_text(name);
- }
+fn render(ctx: RenderContext<'_>, const_: hir::Const) -> Option<CompletionItem> {
+ let db = ctx.db();
+ let name = const_.name(db)?.to_smol_str();
+ // FIXME: This is parsing files!
+ let detail = const_label(&const_.source(db)?.value);
+
+ let mut item = CompletionItem::new(SymbolKind::Const, ctx.source_range(), name.clone());
+ item.set_documentation(ctx.docs(const_))
+ .set_deprecated(ctx.is_deprecated(const_) || ctx.is_deprecated_assoc_item(const_))
+ .detail(detail);
+
+ if let Some(actm) = const_.as_assoc_item(db) {
+ if let Some(trt) = actm.containing_trait_or_trait_impl(db) {
+ item.trait_name(trt.name(db).to_smol_str());
+ item.insert_text(name);
}
-
- Some(item.build())
}
- fn detail(&self) -> String {
- const_label(&self.ast_node)
- }
+ Some(item.build())
}
diff --git a/crates/ide_completion/src/render/enum_variant.rs b/crates/ide_completion/src/render/enum_variant.rs
index 26cb73d09c..f613f0dfde 100644
--- a/crates/ide_completion/src/render/enum_variant.rs
+++ b/crates/ide_completion/src/render/enum_variant.rs
@@ -1,10 +1,10 @@
//! Renderer for `enum` variants.
-use std::{iter, mem};
+use std::iter;
-use hir::{HasAttrs, HirDisplay};
+use hir::{db::HirDatabase, HasAttrs, HirDisplay, StructKind};
use ide_db::SymbolKind;
-use stdx::format_to;
+use itertools::Itertools;
use crate::{
item::{CompletionItem, ImportEdit},
@@ -20,116 +20,86 @@ pub(crate) fn render_variant(
path: Option<hir::ModPath>,
) -> CompletionItem {
let _p = profile::span("render_enum_variant");
- EnumRender::new(ctx, local_name, variant, path).render(import_to_add)
+ render(ctx, local_name, variant, path, import_to_add)
}
-#[derive(Debug)]
-struct EnumRender<'a> {
- ctx: RenderContext<'a>,
+fn render(
+ ctx @ RenderContext { completion }: RenderContext<'_>,
+ local_name: Option<hir::Name>,
variant: hir::Variant,
path: Option<hir::ModPath>,
- qualified_name: hir::ModPath,
- short_qualified_name: hir::ModPath,
- variant_kind: hir::StructKind,
-}
-
-impl<'a> EnumRender<'a> {
- fn new(
- ctx: RenderContext<'a>,
- local_name: Option<hir::Name>,
- variant: hir::Variant,
- path: Option<hir::ModPath>,
- ) -> EnumRender<'a> {
- let name = local_name.unwrap_or_else(|| variant.name(ctx.db()));
- let variant_kind = variant.kind(ctx.db());
-
- let (qualified_name, short_qualified_name) = match &path {
- Some(path) => {
- let short = hir::ModPath::from_segments(
- hir::PathKind::Plain,
- path.segments().iter().skip(path.segments().len().saturating_sub(2)).cloned(),
- );
- (path.clone(), short)
- }
- None => (
- hir::ModPath::from_segments(hir::PathKind::Plain, iter::once(name.clone())),
- hir::ModPath::from_segments(hir::PathKind::Plain, iter::once(name)),
- ),
- };
-
- EnumRender { ctx, variant, path, qualified_name, short_qualified_name, variant_kind }
- }
- fn render(self, import_to_add: Option<ImportEdit>) -> CompletionItem {
- let mut item = CompletionItem::new(
- SymbolKind::Variant,
- self.ctx.source_range(),
- self.qualified_name.to_string(),
- );
- item.set_documentation(self.variant.docs(self.ctx.db()))
- .set_deprecated(self.ctx.is_deprecated(self.variant))
- .detail(self.detail());
-
- if let Some(import_to_add) = import_to_add {
- item.add_import(import_to_add);
- }
-
- if self.variant_kind == hir::StructKind::Tuple {
- cov_mark::hit!(inserts_parens_for_tuple_enums);
- let params = Params::Anonymous(self.variant.fields(self.ctx.db()).len());
- item.add_call_parens(
- self.ctx.completion,
- self.short_qualified_name.to_string(),
- params,
+ import_to_add: Option<ImportEdit>,
+) -> CompletionItem {
+ let db = completion.db;
+ let name = local_name.unwrap_or_else(|| variant.name(db));
+ let variant_kind = variant.kind(db);
+
+ let (qualified_name, short_qualified_name, qualified) = match path {
+ Some(path) => {
+ let short = hir::ModPath::from_segments(
+ hir::PathKind::Plain,
+ path.segments().iter().skip(path.segments().len().saturating_sub(2)).cloned(),
);
- } else if self.path.is_some() {
- item.lookup_by(self.short_qualified_name.to_string());
+ (path, short, true)
}
+ None => (
+ hir::ModPath::from_segments(hir::PathKind::Plain, iter::once(name.clone())),
+ hir::ModPath::from_segments(hir::PathKind::Plain, iter::once(name)),
+ false,
+ ),
+ };
+
+ // FIXME: ModPath::to_smol_str()?
+ let mut item =
+ CompletionItem::new(SymbolKind::Variant, ctx.source_range(), qualified_name.to_string());
+ item.set_documentation(variant.docs(db))
+ .set_deprecated(ctx.is_deprecated(variant))
+ .detail(detail(db, variant, variant_kind));
+
+ if let Some(import_to_add) = import_to_add {
+ item.add_import(import_to_add);
+ }
- let ty = self.variant.parent_enum(self.ctx.completion.db).ty(self.ctx.completion.db);
- item.set_relevance(CompletionRelevance {
- type_match: compute_type_match(self.ctx.completion, &ty),
- ..CompletionRelevance::default()
- });
+ // FIXME: ModPath::to_smol_str()?
+ let short_qualified_name = short_qualified_name.to_string();
+ if variant_kind == hir::StructKind::Tuple {
+ cov_mark::hit!(inserts_parens_for_tuple_enums);
+ let params = Params::Anonymous(variant.fields(db).len());
+ item.add_call_parens(ctx.completion, short_qualified_name, params);
+ } else if qualified {
+ item.lookup_by(short_qualified_name);
+ }
- if let Some(ref_match) = compute_ref_match(self.ctx.completion, &ty) {
- item.ref_match(ref_match);
- }
+ let ty = variant.parent_enum(ctx.completion.db).ty(ctx.completion.db);
+ item.set_relevance(CompletionRelevance {
+ type_match: compute_type_match(ctx.completion, &ty),
+ ..CompletionRelevance::default()
+ });
- item.build()
+ if let Some(ref_match) = compute_ref_match(ctx.completion, &ty) {
+ item.ref_match(ref_match);
}
- fn detail(&self) -> String {
- let detail_types = self
- .variant
- .fields(self.ctx.db())
- .into_iter()
- .map(|field| (field.name(self.ctx.db()), field.ty(self.ctx.db())));
-
- let mut b = String::new();
- let mut first_run = true;
- match self.variant_kind {
- hir::StructKind::Tuple | hir::StructKind::Unit => {
- format_to!(b, "(");
- for (_, t) in detail_types {
- if !mem::take(&mut first_run) {
- format_to!(b, ", ");
- }
- format_to!(b, "{}", t.display(self.ctx.db()));
- }
- format_to!(b, ")");
- }
- hir::StructKind::Record => {
- format_to!(b, "{{");
- for (n, t) in detail_types {
- if !mem::take(&mut first_run) {
- format_to!(b, ", ");
- }
- format_to!(b, "{}: {}", n, t.display(self.ctx.db()));
- }
- format_to!(b, "}}");
- }
+ item.build()
+}
+
+fn detail(db: &dyn HirDatabase, variant: hir::Variant, variant_kind: StructKind) -> String {
+ let detail_types = variant.fields(db).into_iter().map(|field| (field.name(db), field.ty(db)));
+
+ match variant_kind {
+ hir::StructKind::Tuple | hir::StructKind::Unit => {
+ format!("({})", detail_types.format_with(", ", |(_, t), f| f(&t.display(db))))
+ }
+ hir::StructKind::Record => {
+ format!(
+ "{{{}}}",
+ detail_types.format_with(", ", |(n, t), f| {
+ f(&n)?;
+ f(&": ")?;
+ f(&t.display(db))
+ }),
+ )
}
- b
}
}
diff --git a/crates/ide_completion/src/render/function.rs b/crates/ide_completion/src/render/function.rs
index 918210f2f3..f166b87ab6 100644
--- a/crates/ide_completion/src/render/function.rs
+++ b/crates/ide_completion/src/render/function.rs
@@ -1,11 +1,12 @@
//! Renderer for function calls.
-use hir::{AsAssocItem, HirDisplay};
+use hir::{db::HirDatabase, AsAssocItem, HirDisplay};
use ide_db::SymbolKind;
use itertools::Itertools;
use stdx::format_to;
use crate::{
+ context::CompletionContext,
item::{CompletionItem, CompletionItemKind, CompletionRelevance, ImportEdit},
render::{
builder_ext::Params, compute_exact_name_match, compute_ref_match, compute_type_match,
@@ -13,14 +14,19 @@ use crate::{
},
};
+enum FuncType {
+ Function,
+ Method(Option<hir::Name>),
+}
+
pub(crate) fn render_fn(
ctx: RenderContext<'_>,
import_to_add: Option<ImportEdit>,
local_name: Option<hir::Name>,
- fn_: hir::Function,
-) -> Option<CompletionItem> {
+ func: hir::Function,
+) -> CompletionItem {
let _p = profile::span("render_fn");
- Some(FunctionRender::new(ctx, None, local_name, fn_, false)?.render(import_to_add))
+ render(ctx, local_name, func, FuncType::Function, import_to_add)
}
pub(crate) fn render_method(
@@ -28,135 +34,120 @@ pub(crate) fn render_method(
import_to_add: Option<ImportEdit>,
receiver: Option<hir::Name>,
local_name: Option<hir::Name>,
- fn_: hir::Function,
-) -> Option<CompletionItem> {
+ func: hir::Function,
+) -> CompletionItem {
let _p = profile::span("render_method");
- Some(FunctionRender::new(ctx, receiver, local_name, fn_, true)?.render(import_to_add))
+ render(ctx, local_name, func, FuncType::Method(receiver), import_to_add)
}
-#[derive(Debug)]
-struct FunctionRender<'a> {
- ctx: RenderContext<'a>,
- name: hir::Name,
- receiver: Option<hir::Name>,
+fn render(
+ ctx @ RenderContext { completion }: RenderContext<'_>,
+ local_name: Option<hir::Name>,
func: hir::Function,
- is_method: bool,
-}
-
-impl<'a> FunctionRender<'a> {
- fn new(
- ctx: RenderContext<'a>,
- receiver: Option<hir::Name>,
- local_name: Option<hir::Name>,
- fn_: hir::Function,
- is_method: bool,
- ) -> Option<FunctionRender<'a>> {
- let name = local_name.unwrap_or_else(|| fn_.name(ctx.db()));
-
- Some(FunctionRender { ctx, name, receiver, func: fn_, is_method })
- }
+ func_type: FuncType,
+ import_to_add: Option<ImportEdit>,
+) -> CompletionItem {
+ let db = completion.db;
- fn render(self, import_to_add: Option<ImportEdit>) -> CompletionItem {
- let params = self.params();
- let call = match &self.receiver {
- Some(receiver) => format!("{}.{}", receiver, &self.name),
- None => self.name.to_string(),
- };
- let mut item = CompletionItem::new(self.kind(), self.ctx.source_range(), call.clone());
- item.set_documentation(self.ctx.docs(self.func))
- .set_deprecated(
- self.ctx.is_deprecated(self.func) || self.ctx.is_deprecated_assoc_item(self.func),
- )
- .detail(self.detail())
- .add_call_parens(self.ctx.completion, call.clone(), params);
-
- if import_to_add.is_none() {
- let db = self.ctx.db();
- if let Some(actm) = self.func.as_assoc_item(db) {
- if let Some(trt) = actm.containing_trait_or_trait_impl(db) {
- item.trait_name(trt.name(db).to_smol_str());
- }
- }
- }
+ let name = local_name.unwrap_or_else(|| func.name(db));
+ let params = params(completion, func, &func_type);
- if let Some(import_to_add) = import_to_add {
- item.add_import(import_to_add);
- }
- item.lookup_by(self.name.to_smol_str());
-
- let ret_type = self.func.ret_type(self.ctx.db());
- item.set_relevance(CompletionRelevance {
- type_match: compute_type_match(self.ctx.completion, &ret_type),
- exact_name_match: compute_exact_name_match(self.ctx.completion, &call),
- ..CompletionRelevance::default()
- });
-
- if let Some(ref_match) = compute_ref_match(self.ctx.completion, &ret_type) {
- // FIXME
- // For now we don't properly calculate the edits for ref match
- // completions on methods, so we've disabled them. See #8058.
- if !self.is_method {
- item.ref_match(ref_match);
+ // FIXME: SmolStr?
+ let call = match &func_type {
+ FuncType::Method(Some(receiver)) => format!("{}.{}", receiver, &name),
+ _ => name.to_string(),
+ };
+ let mut item = CompletionItem::new(
+ if func.self_param(db).is_some() {
+ CompletionItemKind::Method
+ } else {
+ CompletionItemKind::SymbolKind(SymbolKind::Function)
+ },
+ ctx.source_range(),
+ call.clone(),
+ );
+ item.set_documentation(ctx.docs(func))
+ .set_deprecated(ctx.is_deprecated(func) || ctx.is_deprecated_assoc_item(func))
+ .detail(detail(db, func))
+ .add_call_parens(completion, call.clone(), params);
+
+ if import_to_add.is_none() {
+ if let Some(actm) = func.as_assoc_item(db) {
+ if let Some(trt) = actm.containing_trait_or_trait_impl(db) {
+ item.trait_name(trt.name(db).to_smol_str());
}
}
-
- item.build()
}
- fn detail(&self) -> String {
- let ret_ty = self.func.ret_type(self.ctx.db());
- let mut detail = format!("fn({})", self.params_display());
- if !ret_ty.is_unit() {
- format_to!(detail, " -> {}", ret_ty.display(self.ctx.db()));
+ if let Some(import_to_add) = import_to_add {
+ item.add_import(import_to_add);
+ }
+ item.lookup_by(name.to_smol_str());
+
+ let ret_type = func.ret_type(db);
+ item.set_relevance(CompletionRelevance {
+ type_match: compute_type_match(completion, &ret_type),
+ exact_name_match: compute_exact_name_match(completion, &call),
+ ..CompletionRelevance::default()
+ });
+
+ if let Some(ref_match) = compute_ref_match(completion, &ret_type) {
+ // FIXME
+ // For now we don't properly calculate the edits for ref match
+ // completions on methods, so we've disabled them. See #8058.
+ if matches!(func_type, FuncType::Function) {
+ item.ref_match(ref_match);
}
- detail
}
- fn params_display(&self) -> String {
- if let Some(self_param) = self.func.self_param(self.ctx.db()) {
- let params = self
- .func
- .assoc_fn_params(self.ctx.db())
- .into_iter()
- .skip(1) // skip the self param because we are manually handling that
- .map(|p| p.ty().display(self.ctx.db()).to_string());
+ item.build()
+}
- std::iter::once(self_param.display(self.ctx.db()).to_owned()).chain(params).join(", ")
- } else {
- let params = self
- .func
- .assoc_fn_params(self.ctx.db())
- .into_iter()
- .map(|p| p.ty().display(self.ctx.db()).to_string())
- .join(", ");
- params
- }
+fn detail(db: &dyn HirDatabase, func: hir::Function) -> String {
+ let ret_ty = func.ret_type(db);
+ let mut detail = format!("fn({})", params_display(db, func));
+ if !ret_ty.is_unit() {
+ format_to!(detail, " -> {}", ret_ty.display(db));
}
+ detail
+}
- fn params(&self) -> Params {
- let (params, self_param) =
- if self.ctx.completion.has_dot_receiver() || self.receiver.is_some() {
- (self.func.method_params(self.ctx.db()).unwrap_or_default(), None)
- } else {
- let self_param = self.func.self_param(self.ctx.db());
-
- let mut assoc_params = self.func.assoc_fn_params(self.ctx.db());
- if self_param.is_some() {
- assoc_params.remove(0);
- }
- (assoc_params, self_param)
- };
-
- Params::Named(self_param, params)
+fn params_display(db: &dyn HirDatabase, func: hir::Function) -> String {
+ if let Some(self_param) = func.self_param(db) {
+ let assoc_fn_params = func.assoc_fn_params(db);
+ let params = assoc_fn_params
+ .iter()
+ .skip(1) // skip the self param because we are manually handling that
+ .map(|p| p.ty().display(db));
+ format!(
+ "{}{}",
+ self_param.display(db),
+ params.format_with("", |display, f| {
+ f(&", ")?;
+ f(&display)
+ })
+ )
+ } else {
+ let assoc_fn_params = func.assoc_fn_params(db);
+ assoc_fn_params.iter().map(|p| p.ty().display(db)).join(", ")
}
+}
- fn kind(&self) -> CompletionItemKind {
- if self.func.self_param(self.ctx.db()).is_some() {
- CompletionItemKind::Method
+fn params(ctx: &CompletionContext<'_>, func: hir::Function, func_type: &FuncType) -> Params {
+ let (params, self_param) =
+ if ctx.has_dot_receiver() || matches!(func_type, FuncType::Method(Some(_))) {
+ (func.method_params(ctx.db).unwrap_or_default(), None)
} else {
- SymbolKind::Function.into()
- }
- }
+ let self_param = func.self_param(ctx.db);
+
+ let mut assoc_params = func.assoc_fn_params(ctx.db);
+ if self_param.is_some() {
+ assoc_params.remove(0);
+ }
+ (assoc_params, self_param)
+ };
+
+ Params::Named(self_param, params)
}
#[cfg(test)]
diff --git a/crates/ide_completion/src/render/macro_.rs b/crates/ide_completion/src/render/macro_.rs
index ac1f152aea..9c7b9a6db3 100644
--- a/crates/ide_completion/src/render/macro_.rs
+++ b/crates/ide_completion/src/render/macro_.rs
@@ -1,7 +1,7 @@
//! Renderer for macro invocations.
use either::Either;
-use hir::HasSource;
+use hir::{db::HirDatabase, Documentation, HasSource};
use ide_db::SymbolKind;
use syntax::{
display::{fn_as_proc_macro_label, macro_label},
@@ -21,94 +21,96 @@ pub(crate) fn render_macro(
macro_: hir::MacroDef,
) -> Option<CompletionItem> {
let _p = profile::span("render_macro");
- MacroRender::new(ctx, name, macro_).render(import_to_add)
+ render(ctx, name, macro_, import_to_add)
}
-#[derive(Debug)]
-struct MacroRender<'a> {
- ctx: RenderContext<'a>,
- name: SmolStr,
+fn render(
+ ctx @ RenderContext { completion }: RenderContext<'_>,
+ name: hir::Name,
macro_: hir::MacroDef,
- docs: Option<hir::Documentation>,
- bra: &'static str,
- ket: &'static str,
-}
+ import_to_add: Option<ImportEdit>,
+) -> Option<CompletionItem> {
+ let db = completion.db;
-impl<'a> MacroRender<'a> {
- fn new(ctx: RenderContext<'a>, name: hir::Name, macro_: hir::MacroDef) -> MacroRender<'a> {
- let name = name.to_smol_str();
- let docs = ctx.docs(macro_);
- let docs_str = docs.as_ref().map_or("", |s| s.as_str());
- let (bra, ket) =
- if macro_.is_fn_like() { guess_macro_braces(&name, docs_str) } else { ("", "") };
+ let source_range = if completion.is_immediately_after_macro_bang() {
+ cov_mark::hit!(completes_macro_call_if_cursor_at_bang_token);
+ completion.token.parent().map(|it| it.text_range())
+ } else {
+ Some(ctx.source_range())
+ }?;
- MacroRender { ctx, name, macro_, docs, bra, ket }
- }
+ let name = name.to_smol_str();
+ let docs = ctx.docs(macro_);
+ let docs_str = docs.as_ref().map(Documentation::as_str).unwrap_or_default();
+ let (bra, ket) =
+ if macro_.is_fn_like() { guess_macro_braces(&name, docs_str) } else { ("", "") };
- fn render(self, import_to_add: Option<ImportEdit>) -> Option<CompletionItem> {
- let source_range = if self.ctx.completion.is_immediately_after_macro_bang() {
- cov_mark::hit!(completes_macro_call_if_cursor_at_bang_token);
- self.ctx.completion.token.parent().map(|it| it.text_range())
- } else {
- Some(self.ctx.source_range())
- }?;
- let mut item =
- CompletionItem::new(SymbolKind::from(self.macro_.kind()), source_range, self.label());
- item.set_deprecated(self.ctx.is_deprecated(self.macro_)).set_detail(self.detail());
+ let needs_bang = macro_.is_fn_like()
+ && !matches!(completion.path_kind(), Some(PathKind::Mac | PathKind::Use));
- if let Some(import_to_add) = import_to_add {
- item.add_import(import_to_add);
- }
+ let mut item = CompletionItem::new(
+ SymbolKind::from(macro_.kind()),
+ source_range,
+ label(&ctx, needs_bang, bra, ket, &name),
+ );
+ item.set_deprecated(ctx.is_deprecated(macro_))
+ .set_detail(detail(db, macro_))
+ .set_documentation(docs);
- let needs_bang = self.macro_.is_fn_like()
- && !matches!(self.ctx.completion.path_kind(), Some(PathKind::Mac | PathKind::Use));
- let has_parens = self.ctx.completion.path_is_call();
+ if let Some(import_to_add) = import_to_add {
+ item.add_import(import_to_add);
+ }
- match self.ctx.snippet_cap() {
- Some(cap) if needs_bang && !has_parens => {
- let snippet = format!("{}!{}$0{}", self.name, self.bra, self.ket);
- let lookup = self.banged_name();
- item.insert_snippet(cap, snippet).lookup_by(lookup);
- }
- _ if needs_bang => {
- let lookup = self.banged_name();
- item.insert_text(self.banged_name()).lookup_by(lookup);
- }
- _ => {
- cov_mark::hit!(dont_insert_macro_call_parens_unncessary);
- item.insert_text(&*self.name);
- }
- };
+ let name = &*name;
- item.set_documentation(self.docs);
- Some(item.build())
- }
+ match ctx.snippet_cap() {
+ Some(cap) if needs_bang && !completion.path_is_call() => {
+ let snippet = format!("{}!{}$0{}", name, bra, ket);
+ let lookup = banged_name(name);
+ item.insert_snippet(cap, snippet).lookup_by(lookup);
+ }
+ _ if needs_bang => {
+ let banged_name = banged_name(name);
+ item.insert_text(banged_name.clone()).lookup_by(banged_name);
+ }
+ _ => {
+ cov_mark::hit!(dont_insert_macro_call_parens_unncessary);
+ item.insert_text(name);
+ }
+ };
- fn needs_bang(&self) -> bool {
- !matches!(self.ctx.completion.path_kind(), Some(PathKind::Mac | PathKind::Use))
- }
+ Some(item.build())
+}
- fn label(&self) -> SmolStr {
- if !self.macro_.is_fn_like() {
- self.name.clone()
- } else if self.needs_bang() && self.ctx.snippet_cap().is_some() {
- SmolStr::from_iter([&*self.name, "!", self.bra, "…", self.ket])
+fn label(
+ ctx: &RenderContext<'_>,
+ needs_bang: bool,
+ bra: &str,
+ ket: &str,
+ name: &SmolStr,
+) -> SmolStr {
+ if needs_bang {
+ if ctx.snippet_cap().is_some() {
+ SmolStr::from_iter([&*name, "!", bra, "…", ket])
} else {
- self.banged_name()
+ banged_name(name)
}
+ } else {
+ name.clone()
}
+}
- fn banged_name(&self) -> SmolStr {
- SmolStr::from_iter([&*self.name, "!"])
- }
+fn banged_name(name: &str) -> SmolStr {
+ SmolStr::from_iter([name, "!"])
+}
- fn detail(&self) -> Option<String> {
- let detail = match self.macro_.source(self.ctx.db())?.value {
- Either::Left(node) => macro_label(&node),
- Either::Right(node) => fn_as_proc_macro_label(&node),
- };
- Some(detail)
- }
+fn detail(db: &dyn HirDatabase, macro_: hir::MacroDef) -> Option<String> {
+ // FIXME: This is parsing the file!
+ let detail = match macro_.source(db)?.value {
+ Either::Left(node) => macro_label(&node),
+ Either::Right(node) => fn_as_proc_macro_label(&node),
+ };
+ Some(detail)
}
fn guess_macro_braces(macro_name: &str, docs: &str) -> (&'static str, &'static str) {
@@ -147,7 +149,7 @@ mod tests {
fn dont_insert_macro_call_parens_unncessary() {
cov_mark::check!(dont_insert_macro_call_parens_unncessary);
check_edit(
- "frobnicate!",
+ "frobnicate",
r#"
//- /main.rs crate:main deps:foo
use foo::$0;
@@ -161,7 +163,7 @@ use foo::frobnicate;
);
check_edit(
- "frobnicate!",
+ "frobnicate",
r#"
macro_rules! frobnicate { () => () }
fn main() { frob$0!(); }
diff --git a/crates/ide_completion/src/render/type_alias.rs b/crates/ide_completion/src/render/type_alias.rs
index 259fe25a6c..5df21fb36c 100644
--- a/crates/ide_completion/src/render/type_alias.rs
+++ b/crates/ide_completion/src/render/type_alias.rs
@@ -2,10 +2,7 @@
use hir::{AsAssocItem, HasSource};
use ide_db::SymbolKind;
-use syntax::{
- ast::{HasName, TypeAlias},
- display::type_label,
-};
+use syntax::{ast::HasName, display::type_label};
use crate::{item::CompletionItem, render::RenderContext};
@@ -14,7 +11,7 @@ pub(crate) fn render_type_alias(
type_alias: hir::TypeAlias,
) -> Option<CompletionItem> {
let _p = profile::span("render_type_alias");
- TypeAliasRender::new(ctx, type_alias)?.render(false)
+ render(ctx, type_alias, false)
}
pub(crate) fn render_type_alias_with_eq(
@@ -22,53 +19,38 @@ pub(crate) fn render_type_alias_with_eq(
type_alias: hir::TypeAlias,
) -> Option<CompletionItem> {
let _p = profile::span("render_type_alias_with_eq");
- TypeAliasRender::new(ctx, type_alias)?.render(true)
+ render(ctx, type_alias, true)
}
-#[derive(Debug)]
-struct TypeAliasRender<'a> {
- ctx: RenderContext<'a>,
+fn render(
+ ctx: RenderContext<'_>,
type_alias: hir::TypeAlias,
- ast_node: TypeAlias,
-}
-
-impl<'a> TypeAliasRender<'a> {
- fn new(ctx: RenderContext<'a>, type_alias: hir::TypeAlias) -> Option<TypeAliasRender<'a>> {
- let ast_node = type_alias.source(ctx.db())?.value;
- Some(TypeAliasRender { ctx, type_alias, ast_node })
- }
-
- fn render(self, with_eq: bool) -> Option<CompletionItem> {
- let name = self.ast_node.name().map(|name| {
- if with_eq {
- format!("{} = ", name.text())
- } else {
- name.text().to_string()
- }
- })?;
- let detail = self.detail();
-
- let mut item =
- CompletionItem::new(SymbolKind::TypeAlias, self.ctx.source_range(), name.clone());
- item.set_documentation(self.ctx.docs(self.type_alias))
- .set_deprecated(
- self.ctx.is_deprecated(self.type_alias)
- || self.ctx.is_deprecated_assoc_item(self.type_alias),
- )
- .detail(detail);
-
- let db = self.ctx.db();
- if let Some(actm) = self.type_alias.as_assoc_item(db) {
- if let Some(trt) = actm.containing_trait_or_trait_impl(db) {
- item.trait_name(trt.name(db).to_smol_str());
- item.insert_text(name);
- }
+ with_eq: bool,
+) -> Option<CompletionItem> {
+ let db = ctx.db();
+
+ // FIXME: This parses the file!
+ let ast_node = type_alias.source(db)?.value;
+ let name = ast_node.name().map(|name| {
+ if with_eq {
+ format!("{} = ", name.text())
+ } else {
+ name.text().to_string()
+ }
+ })?;
+ let detail = type_label(&ast_node);
+
+ let mut item = CompletionItem::new(SymbolKind::TypeAlias, ctx.source_range(), name.clone());
+ item.set_documentation(ctx.docs(type_alias))
+ .set_deprecated(ctx.is_deprecated(type_alias) || ctx.is_deprecated_assoc_item(type_alias))
+ .detail(detail);
+
+ if let Some(actm) = type_alias.as_assoc_item(db) {
+ if let Some(trt) = actm.containing_trait_or_trait_impl(db) {
+ item.trait_name(trt.name(db).to_smol_str());
+ item.insert_text(name);
}
-
- Some(item.build())
}
- fn detail(&self) -> String {
- type_label(&self.ast_node)
- }
+ Some(item.build())
}
diff --git a/crates/ide_completion/src/tests/use_tree.rs b/crates/ide_completion/src/tests/use_tree.rs
index 4cde258122..5f20e342e0 100644
--- a/crates/ide_completion/src/tests/use_tree.rs
+++ b/crates/ide_completion/src/tests/use_tree.rs
@@ -129,7 +129,7 @@ struct Bar;
"#,
expect![[r#"
st Foo
- ma foo! macro_rules! foo_
+ ma foo macro_rules! foo_
"#]],
);
}