Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide_completion/src/render.rs')
-rw-r--r--crates/ide_completion/src/render.rs169
1 files changed, 96 insertions, 73 deletions
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs
index 58443f566e..4180d704a3 100644
--- a/crates/ide_completion/src/render.rs
+++ b/crates/ide_completion/src/render.rs
@@ -22,7 +22,7 @@ use crate::{
context::{PathCompletionContext, PathKind},
item::{CompletionRelevanceTypeMatch, ImportEdit},
render::{enum_variant::render_variant, function::render_fn, macro_::render_macro},
- CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, CompletionRelevance,
+ CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance,
};
/// Interface for data and methods required for items rendering.
#[derive(Debug)]
@@ -85,7 +85,7 @@ pub(crate) fn render_field(
let is_deprecated = ctx.is_deprecated(field);
let name = field.name(ctx.db()).to_string();
let mut item = CompletionItem::new(
- CompletionKind::Reference,
+ SymbolKind::Field,
ctx.source_range(),
receiver.map_or_else(|| name.clone(), |receiver| format!("{}.{}", receiver, name)),
);
@@ -94,8 +94,7 @@ pub(crate) fn render_field(
exact_name_match: compute_exact_name_match(ctx.completion, name.as_str()),
..CompletionRelevance::default()
});
- item.kind(SymbolKind::Field)
- .detail(ty.display(ctx.db()).to_string())
+ item.detail(ty.display(ctx.db()).to_string())
.set_documentation(field.docs(ctx.db()))
.set_deprecated(is_deprecated)
.lookup_by(name.as_str());
@@ -118,13 +117,11 @@ pub(crate) fn render_tuple_field(
ty: &hir::Type,
) -> CompletionItem {
let mut item = CompletionItem::new(
- CompletionKind::Reference,
+ SymbolKind::Field,
ctx.source_range(),
receiver.map_or_else(|| field.to_string(), |receiver| format!("{}.{}", receiver, field)),
);
- item.kind(SymbolKind::Field)
- .detail(ty.display(ctx.db()).to_string())
- .lookup_by(field.to_string());
+ item.detail(ty.display(ctx.db()).to_string()).lookup_by(field.to_string());
item.build()
}
@@ -147,10 +144,7 @@ pub(crate) fn render_resolution_with_import(
hir::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).map(|mut item| {
- item.completion_kind = CompletionKind::Magic;
- item
- })
+ render_resolution_(ctx, local_name, Some(import_edit), &resolution)
}
fn render_resolution_(
@@ -162,11 +156,6 @@ fn render_resolution_(
let _p = profile::span("render_resolution");
use hir::ModuleDef::*;
- let completion_kind = match resolution {
- hir::ScopeDef::ModuleDef(BuiltinType(..)) => CompletionKind::BuiltinType,
- _ => CompletionKind::Reference,
- };
-
let kind = match resolution {
hir::ScopeDef::ModuleDef(Function(func)) => {
return render_fn(ctx, import_to_add, Some(local_name), *func);
@@ -208,11 +197,10 @@ fn render_resolution_(
}
hir::ScopeDef::Unknown => {
let mut item = CompletionItem::new(
- CompletionKind::Reference,
+ CompletionItemKind::UnresolvedReference,
ctx.source_range(),
local_name.to_string(),
);
- item.kind(CompletionItemKind::UnresolvedReference);
if let Some(import_to_add) = import_to_add {
item.add_import(import_to_add);
}
@@ -221,7 +209,7 @@ fn render_resolution_(
};
let local_name = local_name.to_string();
- let mut item = CompletionItem::new(completion_kind, ctx.source_range(), local_name.clone());
+ 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 !ty.is_unknown() {
@@ -260,8 +248,7 @@ fn render_resolution_(
}
}
}
- item.kind(kind)
- .set_documentation(scope_def_docs(ctx.db(), resolution))
+ item.set_documentation(scope_def_docs(ctx.db(), resolution))
.set_deprecated(scope_def_is_deprecated(&ctx, resolution));
if let Some(import_to_add) = import_to_add {
@@ -344,37 +331,54 @@ mod tests {
use std::cmp;
use expect_test::{expect, Expect};
+ use ide_db::SymbolKind;
use itertools::Itertools;
use crate::{
item::CompletionRelevanceTypeMatch,
tests::{check_edit, do_completion, get_all_items, TEST_CONFIG},
- CompletionKind, CompletionRelevance,
+ CompletionItem, CompletionItemKind, CompletionRelevance,
};
#[track_caller]
- fn check(ra_fixture: &str, expect: Expect) {
- let actual = do_completion(ra_fixture, CompletionKind::Reference);
+ fn check(ra_fixture: &str, kind: impl Into<CompletionItemKind>, expect: Expect) {
+ let actual = do_completion(ra_fixture, kind.into());
expect.assert_debug_eq(&actual);
}
#[track_caller]
- fn check_relevance(ra_fixture: &str, expect: Expect) {
- check_relevance_for_kinds(&[CompletionKind::Reference], ra_fixture, expect)
+ fn check_kinds(ra_fixture: &str, kinds: &[CompletionItemKind], expect: Expect) {
+ let actual: Vec<_> =
+ kinds.iter().flat_map(|&kind| do_completion(ra_fixture, kind)).collect();
+ expect.assert_debug_eq(&actual);
+ }
+
+ #[track_caller]
+ fn check_relevance_for_kinds(ra_fixture: &str, kinds: &[CompletionItemKind], expect: Expect) {
+ let mut actual = get_all_items(TEST_CONFIG, ra_fixture);
+ actual.retain(|it| kinds.contains(&it.kind()));
+ actual.sort_by_key(|it| cmp::Reverse(it.relevance().score()));
+ check_relevance_(actual, expect);
}
#[track_caller]
- fn check_relevance_for_kinds(kinds: &[CompletionKind], ra_fixture: &str, expect: Expect) {
+ fn check_relevance(ra_fixture: &str, expect: Expect) {
let mut actual = get_all_items(TEST_CONFIG, ra_fixture);
- actual.retain(|it| kinds.contains(&it.completion_kind));
+ actual.retain(|it| it.kind() != CompletionItemKind::Snippet);
+ actual.retain(|it| it.kind() != CompletionItemKind::Keyword);
+ actual.retain(|it| it.kind() != CompletionItemKind::BuiltinType);
actual.sort_by_key(|it| cmp::Reverse(it.relevance().score()));
+ check_relevance_(actual, expect);
+ }
+ #[track_caller]
+ fn check_relevance_(actual: Vec<CompletionItem>, expect: Expect) {
let actual = actual
.into_iter()
.flat_map(|it| {
let mut items = vec![];
- let tag = it.kind().unwrap().tag();
+ let tag = it.kind().tag();
let relevance = display_relevance(it.relevance());
items.push(format!("{} {} {}\n", tag, it.label(), relevance));
@@ -418,6 +422,7 @@ enum Foo { Foo { x: i32, y: i32 } }
fn main() { Foo::Fo$0 }
"#,
+ SymbolKind::Variant,
expect![[r#"
[
CompletionItem {
@@ -443,6 +448,7 @@ enum Foo { Foo (i32, i32) }
fn main() { Foo::Fo$0 }
"#,
+ SymbolKind::Variant,
expect![[r#"
[
CompletionItem {
@@ -470,6 +476,7 @@ fn foo<T>(a: u32, b: u32, t: T) -> (u32, T) { (a, t) }
fn main() { fo$0 }
"#,
+ SymbolKind::Function,
expect![[r#"
[
CompletionItem {
@@ -508,6 +515,7 @@ enum Foo { Foo }
fn main() { Foo::Fo$0 }
"#,
+ SymbolKind::Variant,
expect![[r#"
[
CompletionItem {
@@ -527,16 +535,41 @@ fn main() { Foo::Fo$0 }
#[test]
fn lookup_enums_by_two_qualifiers() {
- check(
+ check_kinds(
r#"
mod m {
pub enum Spam { Foo, Bar(i32) }
}
fn main() { let _: m::Spam = S$0 }
"#,
+ &[
+ CompletionItemKind::SymbolKind(SymbolKind::Function),
+ CompletionItemKind::SymbolKind(SymbolKind::Module),
+ CompletionItemKind::SymbolKind(SymbolKind::Variant),
+ ],
expect![[r#"
[
CompletionItem {
+ label: "main()",
+ source_range: 75..76,
+ delete: 75..76,
+ insert: "main()$0",
+ kind: SymbolKind(
+ Function,
+ ),
+ lookup: "main",
+ detail: "fn()",
+ },
+ CompletionItem {
+ label: "m",
+ source_range: 75..76,
+ delete: 75..76,
+ insert: "m",
+ kind: SymbolKind(
+ Module,
+ ),
+ },
+ CompletionItem {
label: "Spam::Bar(…)",
source_range: 75..76,
delete: 75..76,
@@ -557,15 +590,6 @@ fn main() { let _: m::Spam = S$0 }
trigger_call_info: true,
},
CompletionItem {
- label: "m",
- source_range: 75..76,
- delete: 75..76,
- insert: "m",
- kind: SymbolKind(
- Module,
- ),
- },
- CompletionItem {
label: "m::Spam::Foo",
source_range: 75..76,
delete: 75..76,
@@ -584,17 +608,6 @@ fn main() { let _: m::Spam = S$0 }
exact_postfix_snippet_match: false,
},
},
- CompletionItem {
- label: "main()",
- source_range: 75..76,
- delete: 75..76,
- insert: "main()$0",
- kind: SymbolKind(
- Function,
- ),
- lookup: "main",
- detail: "fn()",
- },
]
"#]],
)
@@ -611,6 +624,7 @@ fn something_else_deprecated() {}
fn main() { som$0 }
"#,
+ SymbolKind::Function,
expect![[r#"
[
CompletionItem {
@@ -657,6 +671,7 @@ fn main() { som$0 }
struct A { #[deprecated] the_field: u32 }
fn foo() { A { the$0 } }
"#,
+ SymbolKind::Field,
expect![[r#"
[
CompletionItem {
@@ -685,7 +700,7 @@ fn foo() { A { the$0 } }
#[test]
fn renders_docs() {
- check(
+ check_kinds(
r#"
struct S {
/// Field docs
@@ -695,6 +710,7 @@ impl S {
/// Method docs
fn bar(self) { self.$0 }
}"#,
+ &[CompletionItemKind::Method, CompletionItemKind::SymbolKind(SymbolKind::Field)],
expect![[r#"
[
CompletionItem {
@@ -726,7 +742,7 @@ impl S {
"#]],
);
- check(
+ check_kinds(
r#"
use self::my$0;
@@ -740,18 +756,23 @@ enum E {
}
use self::E::*;
"#,
+ &[
+ CompletionItemKind::SymbolKind(SymbolKind::Module),
+ CompletionItemKind::SymbolKind(SymbolKind::Variant),
+ CompletionItemKind::SymbolKind(SymbolKind::Enum),
+ ],
expect![[r#"
[
CompletionItem {
- label: "E",
+ label: "my",
source_range: 10..12,
delete: 10..12,
- insert: "E",
+ insert: "my",
kind: SymbolKind(
- Enum,
+ Module,
),
documentation: Documentation(
- "enum docs",
+ "mod docs",
),
},
CompletionItem {
@@ -768,15 +789,15 @@ use self::E::*;
),
},
CompletionItem {
- label: "my",
+ label: "E",
source_range: 10..12,
delete: 10..12,
- insert: "my",
+ insert: "E",
kind: SymbolKind(
- Module,
+ Enum,
),
documentation: Documentation(
- "mod docs",
+ "enum docs",
),
},
]
@@ -795,6 +816,7 @@ impl S {
}
fn foo(s: S) { s.$0 }
"#,
+ CompletionItemKind::Method,
expect![[r#"
[
CompletionItem {
@@ -1318,19 +1340,29 @@ fn main() {
#[test]
fn struct_field_method_ref() {
- check(
+ check_kinds(
r#"
struct Foo { bar: u32 }
impl Foo { fn baz(&self) -> u32 { 0 } }
fn foo(f: Foo) { let _: &u32 = f.b$0 }
"#,
+ &[CompletionItemKind::Method, CompletionItemKind::SymbolKind(SymbolKind::Field)],
// FIXME
// Ideally we'd also suggest &f.bar and &f.baz() as exact
// type matches. See #8058.
expect![[r#"
[
CompletionItem {
+ label: "baz()",
+ source_range: 98..99,
+ delete: 98..99,
+ insert: "baz()$0",
+ kind: Method,
+ lookup: "baz",
+ detail: "fn(&self) -> u32",
+ },
+ CompletionItem {
label: "bar",
source_range: 98..99,
delete: 98..99,
@@ -1340,15 +1372,6 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 }
),
detail: "u32",
},
- CompletionItem {
- label: "baz()",
- source_range: 98..99,
- delete: 98..99,
- insert: "baz()$0",
- kind: Method,
- lookup: "baz",
- detail: "fn(&self) -> u32",
- },
]
"#]],
);
@@ -1387,7 +1410,6 @@ fn foo() {
#[test]
fn postfix_completion_relevance() {
check_relevance_for_kinds(
- &[CompletionKind::Postfix, CompletionKind::Magic],
r#"
mod ops {
pub trait Not {
@@ -1404,7 +1426,8 @@ mod ops {
fn main() {
let _: bool = (9 > 2).not$0;
}
-"#,
+ "#,
+ &[CompletionItemKind::Snippet, CompletionItemKind::Method],
expect![[r#"
sn not [snippet]
me not() (use ops::Not) [type_could_unify]