Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/ide_completion/src/completions.rs9
-rw-r--r--crates/ide_completion/src/completions/attribute.rs8
-rw-r--r--crates/ide_completion/src/completions/attribute/cfg.rs10
-rw-r--r--crates/ide_completion/src/completions/attribute/derive.rs6
-rw-r--r--crates/ide_completion/src/completions/attribute/lint.rs8
-rw-r--r--crates/ide_completion/src/completions/attribute/repr.rs5
-rw-r--r--crates/ide_completion/src/completions/dot.rs13
-rw-r--r--crates/ide_completion/src/completions/flyimport.rs1015
-rw-r--r--crates/ide_completion/src/completions/fn_param.rs6
-rw-r--r--crates/ide_completion/src/completions/keyword.rs300
-rw-r--r--crates/ide_completion/src/completions/mod_.rs8
-rw-r--r--crates/ide_completion/src/completions/postfix.rs24
-rw-r--r--crates/ide_completion/src/completions/qualified_path.rs7
-rw-r--r--crates/ide_completion/src/completions/record.rs16
-rw-r--r--crates/ide_completion/src/completions/snippet.rs6
-rw-r--r--crates/ide_completion/src/completions/trait_impl.rs78
-rw-r--r--crates/ide_completion/src/completions/unqualified_path.rs17
-rw-r--r--crates/ide_completion/src/context.rs1
-rw-r--r--crates/ide_completion/src/item.rs41
-rw-r--r--crates/ide_completion/src/lib.rs2
-rw-r--r--crates/ide_completion/src/render.rs169
-rw-r--r--crates/ide_completion/src/render/const_.rs10
-rw-r--r--crates/ide_completion/src/render/enum_variant.rs7
-rw-r--r--crates/ide_completion/src/render/function.rs8
-rw-r--r--crates/ide_completion/src/render/macro_.rs7
-rw-r--r--crates/ide_completion/src/render/pattern.rs8
-rw-r--r--crates/ide_completion/src/render/struct_literal.rs10
-rw-r--r--crates/ide_completion/src/render/type_alias.rs10
-rw-r--r--crates/ide_completion/src/tests.rs75
-rw-r--r--crates/ide_completion/src/tests/expression.rs219
-rw-r--r--crates/ide_completion/src/tests/flyimport.rs1014
-rw-r--r--crates/ide_completion/src/tests/record.rs1
-rw-r--r--crates/rust-analyzer/src/to_proto.rs2
-rw-r--r--crates/rust-analyzer/tests/slow-tests/tidy.rs1
34 files changed, 1558 insertions, 1563 deletions
diff --git a/crates/ide_completion/src/completions.rs b/crates/ide_completion/src/completions.rs
index 5f751d83a8..3e658c6e91 100644
--- a/crates/ide_completion/src/completions.rs
+++ b/crates/ide_completion/src/completions.rs
@@ -21,7 +21,7 @@ use hir::known;
use ide_db::SymbolKind;
use crate::{
- item::{Builder, CompletionKind},
+ item::Builder,
render::{
const_::render_const,
enum_variant::render_variant,
@@ -76,8 +76,7 @@ impl Completions {
}
pub(crate) fn add_keyword(&mut self, ctx: &CompletionContext, keyword: &'static str) {
- let mut item = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), keyword);
- item.kind(CompletionItemKind::Keyword);
+ let item = CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), keyword);
item.add_to(self);
}
@@ -191,9 +190,7 @@ impl Completions {
}
pub(crate) fn add_static_lifetime(&mut self, ctx: &CompletionContext) {
- let mut item =
- CompletionItem::new(CompletionKind::Reference, ctx.source_range(), "'static");
- item.kind(CompletionItemKind::SymbolKind(SymbolKind::LifetimeParam));
+ let item = CompletionItem::new(SymbolKind::LifetimeParam, ctx.source_range(), "'static");
self.add(item.build());
}
diff --git a/crates/ide_completion/src/completions/attribute.rs b/crates/ide_completion/src/completions/attribute.rs
index 119572923c..2482418ae6 100644
--- a/crates/ide_completion/src/completions/attribute.rs
+++ b/crates/ide_completion/src/completions/attribute.rs
@@ -12,7 +12,7 @@ use syntax::{algo::non_trivia_sibling, ast, AstNode, Direction, SyntaxKind, T};
use crate::{
context::CompletionContext,
- item::{CompletionItem, CompletionItemKind, CompletionKind},
+ item::{CompletionItem, CompletionItemKind},
Completions,
};
@@ -69,11 +69,10 @@ fn complete_new_attribute(acc: &mut Completions, ctx: &CompletionContext, attrib
let add_completion = |attr_completion: &AttrCompletion| {
let mut item = CompletionItem::new(
- CompletionKind::Attribute,
+ CompletionItemKind::Attribute,
ctx.source_range(),
attr_completion.label,
);
- item.kind(CompletionItemKind::Attribute);
if let Some(lookup) = attr_completion.lookup {
item.lookup_by(lookup);
@@ -103,11 +102,10 @@ fn complete_new_attribute(acc: &mut Completions, ctx: &CompletionContext, attrib
if let hir::ScopeDef::MacroDef(mac) = scope_def {
if mac.kind() == hir::MacroKind::Attr {
let mut item = CompletionItem::new(
- CompletionKind::Attribute,
+ CompletionItemKind::Attribute,
ctx.source_range(),
name.to_string(),
);
- item.kind(CompletionItemKind::Attribute);
if let Some(docs) = mac.docs(ctx.sema.db) {
item.documentation(docs);
}
diff --git a/crates/ide_completion/src/completions/attribute/cfg.rs b/crates/ide_completion/src/completions/attribute/cfg.rs
index 171babc698..c83e1718ec 100644
--- a/crates/ide_completion/src/completions/attribute/cfg.rs
+++ b/crates/ide_completion/src/completions/attribute/cfg.rs
@@ -5,16 +5,14 @@ use std::iter;
use syntax::SyntaxKind;
use crate::{
- completions::Completions, context::CompletionContext, item::CompletionKind, CompletionItem,
- CompletionItemKind,
+ completions::Completions, context::CompletionContext, CompletionItem, CompletionItemKind,
};
pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext) {
let add_completion = |item: &str| {
let mut completion =
- CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), item);
+ CompletionItem::new(CompletionItemKind::Attribute, ctx.source_range(), item);
completion.insert_text(format!(r#""{}""#, item));
- completion.kind(CompletionItemKind::Attribute);
acc.add(completion.build());
};
@@ -35,7 +33,7 @@ pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext) {
if let Some(krate) = ctx.krate {
krate.potential_cfg(ctx.db).get_cfg_values(&name).iter().for_each(|s| {
let mut item = CompletionItem::new(
- CompletionKind::Attribute,
+ CompletionItemKind::Attribute,
ctx.source_range(),
s.as_str(),
);
@@ -49,7 +47,7 @@ pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext) {
if let Some(krate) = ctx.krate {
krate.potential_cfg(ctx.db).get_cfg_keys().iter().for_each(|s| {
let item = CompletionItem::new(
- CompletionKind::Attribute,
+ CompletionItemKind::Attribute,
ctx.source_range(),
s.as_str(),
);
diff --git a/crates/ide_completion/src/completions/attribute/derive.rs b/crates/ide_completion/src/completions/attribute/derive.rs
index e460a91102..7f050f25c9 100644
--- a/crates/ide_completion/src/completions/attribute/derive.rs
+++ b/crates/ide_completion/src/completions/attribute/derive.rs
@@ -7,7 +7,7 @@ use syntax::ast;
use crate::{
context::CompletionContext,
- item::{CompletionItem, CompletionItemKind, CompletionKind},
+ item::{CompletionItem, CompletionItemKind},
Completions,
};
@@ -56,8 +56,8 @@ pub(super) fn complete_derive(
_ => (&*name, None),
};
- let mut item = CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), label);
- item.kind(CompletionItemKind::Attribute);
+ let mut item =
+ CompletionItem::new(CompletionItemKind::Attribute, ctx.source_range(), label);
if let Some(docs) = mac.docs(ctx.db) {
item.documentation(docs);
}
diff --git a/crates/ide_completion/src/completions/attribute/lint.rs b/crates/ide_completion/src/completions/attribute/lint.rs
index 18942f8beb..05a29dd0ae 100644
--- a/crates/ide_completion/src/completions/attribute/lint.rs
+++ b/crates/ide_completion/src/completions/attribute/lint.rs
@@ -4,7 +4,7 @@ use syntax::{ast, T};
use crate::{
context::CompletionContext,
- item::{CompletionItem, CompletionItemKind, CompletionKind},
+ item::{CompletionItem, CompletionItemKind},
Completions,
};
@@ -58,9 +58,9 @@ pub(super) fn complete_lint(
Some(qual) if !is_qualified => format!("{}::{}", qual, name),
_ => name.to_owned(),
};
- let mut item = CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), label);
- item.kind(CompletionItemKind::Attribute)
- .documentation(hir::Documentation::new(description.to_owned()));
+ let mut item =
+ CompletionItem::new(CompletionItemKind::Attribute, ctx.source_range(), label);
+ item.documentation(hir::Documentation::new(description.to_owned()));
item.add_to(acc)
}
}
diff --git a/crates/ide_completion/src/completions/attribute/repr.rs b/crates/ide_completion/src/completions/attribute/repr.rs
index 9a12b8571c..c240912f02 100644
--- a/crates/ide_completion/src/completions/attribute/repr.rs
+++ b/crates/ide_completion/src/completions/attribute/repr.rs
@@ -4,7 +4,7 @@ use syntax::ast;
use crate::{
context::CompletionContext,
- item::{CompletionItem, CompletionItemKind, CompletionKind},
+ item::{CompletionItem, CompletionItemKind},
Completions,
};
@@ -30,8 +30,7 @@ pub(super) fn complete_repr(acc: &mut Completions, ctx: &CompletionContext, inpu
}
let mut item =
- CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), label);
- item.kind(CompletionItemKind::Attribute);
+ CompletionItem::new(CompletionItemKind::Attribute, ctx.source_range(), label);
if let Some(lookup) = lookup {
item.lookup_by(lookup);
}
diff --git a/crates/ide_completion/src/completions/dot.rs b/crates/ide_completion/src/completions/dot.rs
index 213cb70170..ce964e986b 100644
--- a/crates/ide_completion/src/completions/dot.rs
+++ b/crates/ide_completion/src/completions/dot.rs
@@ -99,13 +99,10 @@ fn complete_methods(
mod tests {
use expect_test::{expect, Expect};
- use crate::{
- tests::{check_edit, filtered_completion_list},
- CompletionKind,
- };
+ use crate::tests::{check_edit, completion_list_no_kw};
fn check(ra_fixture: &str, expect: Expect) {
- let actual = filtered_completion_list(ra_fixture, CompletionKind::Reference);
+ let actual = completion_list_no_kw(ra_fixture);
expect.assert_eq(&actual);
}
@@ -166,7 +163,7 @@ impl A {
struct A { the_field: u32 }
fn foo(a: A) { a.$0() }
"#,
- expect![[""]],
+ expect![[r#""#]],
);
}
@@ -405,7 +402,7 @@ fn foo(a: A) {
a.$0
}
"#,
- expect![[""]],
+ expect![[r#""#]],
);
}
@@ -654,6 +651,7 @@ impl Foo { fn foo(&self) { $0 } }"#,
lc self &Foo
sp Self
st Foo
+ bt u32
fd self.field i32
me self.foo() fn(&self)
"#]],
@@ -667,6 +665,7 @@ impl Foo { fn foo(&mut self) { $0 } }"#,
lc self &mut Foo
sp Self
st Foo
+ bt u32
fd self.0 i32
me self.foo() fn(&mut self)
"#]],
diff --git a/crates/ide_completion/src/completions/flyimport.rs b/crates/ide_completion/src/completions/flyimport.rs
index d7c8c54315..486cbff685 100644
--- a/crates/ide_completion/src/completions/flyimport.rs
+++ b/crates/ide_completion/src/completions/flyimport.rs
@@ -219,1018 +219,3 @@ fn compute_fuzzy_completion_order_key(
None => usize::MAX,
}
}
-
-#[cfg(test)]
-mod tests {
- use expect_test::{expect, Expect};
-
- use crate::{
- item::CompletionKind,
- tests::{check_edit, check_edit_with_config, filtered_completion_list, TEST_CONFIG},
- };
-
- fn check(ra_fixture: &str, expect: Expect) {
- let actual = filtered_completion_list(ra_fixture, CompletionKind::Magic);
- expect.assert_eq(&actual);
- }
-
- #[test]
- fn function_fuzzy_completion() {
- check_edit(
- "stdin",
- r#"
-//- /lib.rs crate:dep
-pub mod io {
- pub fn stdin() {}
-};
-
-//- /main.rs crate:main deps:dep
-fn main() {
- stdi$0
-}
-"#,
- r#"
-use dep::io::stdin;
-
-fn main() {
- stdin()$0
-}
-"#,
- );
- }
-
- #[test]
- fn macro_fuzzy_completion() {
- check_edit(
- "macro_with_curlies!",
- r#"
-//- /lib.rs crate:dep
-/// Please call me as macro_with_curlies! {}
-#[macro_export]
-macro_rules! macro_with_curlies {
- () => {}
-}
-
-//- /main.rs crate:main deps:dep
-fn main() {
- curli$0
-}
-"#,
- r#"
-use dep::macro_with_curlies;
-
-fn main() {
- macro_with_curlies! {$0}
-}
-"#,
- );
- }
-
- #[test]
- fn struct_fuzzy_completion() {
- check_edit(
- "ThirdStruct",
- r#"
-//- /lib.rs crate:dep
-pub struct FirstStruct;
-pub mod some_module {
- pub struct SecondStruct;
- pub struct ThirdStruct;
-}
-
-//- /main.rs crate:main deps:dep
-use dep::{FirstStruct, some_module::SecondStruct};
-
-fn main() {
- this$0
-}
-"#,
- r#"
-use dep::{FirstStruct, some_module::{SecondStruct, ThirdStruct}};
-
-fn main() {
- ThirdStruct
-}
-"#,
- );
- }
-
- #[test]
- fn short_paths_are_ignored() {
- cov_mark::check!(ignore_short_input_for_path);
-
- check(
- r#"
-//- /lib.rs crate:dep
-pub struct FirstStruct;
-pub mod some_module {
- pub struct SecondStruct;
- pub struct ThirdStruct;
-}
-
-//- /main.rs crate:main deps:dep
-use dep::{FirstStruct, some_module::SecondStruct};
-
-fn main() {
- t$0
-}
-"#,
- expect![[r#""#]],
- );
- }
-
- #[test]
- fn fuzzy_completions_come_in_specific_order() {
- cov_mark::check!(certain_fuzzy_order_test);
- check(
- r#"
-//- /lib.rs crate:dep
-pub struct FirstStruct;
-pub mod some_module {
- // already imported, omitted
- pub struct SecondStruct;
- // does not contain all letters from the query, omitted
- pub struct UnrelatedOne;
- // contains all letters from the query, but not in sequence, displayed last
- pub struct ThiiiiiirdStruct;
- // contains all letters from the query, but not in the beginning, displayed second
- pub struct AfterThirdStruct;
- // contains all letters from the query in the begginning, displayed first
- pub struct ThirdStruct;
-}
-
-//- /main.rs crate:main deps:dep
-use dep::{FirstStruct, some_module::SecondStruct};
-
-fn main() {
- hir$0
-}
-"#,
- expect![[r#"
- st ThirdStruct (use dep::some_module::ThirdStruct)
- st AfterThirdStruct (use dep::some_module::AfterThirdStruct)
- st ThiiiiiirdStruct (use dep::some_module::ThiiiiiirdStruct)
- "#]],
- );
- }
-
- #[test]
- fn trait_function_fuzzy_completion() {
- let fixture = r#"
- //- /lib.rs crate:dep
- pub mod test_mod {
- pub trait TestTrait {
- const SPECIAL_CONST: u8;
- type HumbleType;
- fn weird_function();
- fn random_method(&self);
- }
- pub struct TestStruct {}
- impl TestTrait for TestStruct {
- const SPECIAL_CONST: u8 = 42;
- type HumbleType = ();
- fn weird_function() {}
- fn random_method(&self) {}
- }
- }
-
- //- /main.rs crate:main deps:dep
- fn main() {
- dep::test_mod::TestStruct::wei$0
- }
- "#;
-
- check(
- fixture,
- expect![[r#"
- fn weird_function() (use dep::test_mod::TestTrait) fn()
- "#]],
- );
-
- check_edit(
- "weird_function",
- fixture,
- r#"
-use dep::test_mod::TestTrait;
-
-fn main() {
- dep::test_mod::TestStruct::weird_function()$0
-}
-"#,
- );
- }
-
- #[test]
- fn trait_const_fuzzy_completion() {
- let fixture = r#"
- //- /lib.rs crate:dep
- pub mod test_mod {
- pub trait TestTrait {
- const SPECIAL_CONST: u8;
- type HumbleType;
- fn weird_function();
- fn random_method(&self);
- }
- pub struct TestStruct {}
- impl TestTrait for TestStruct {
- const SPECIAL_CONST: u8 = 42;
- type HumbleType = ();
- fn weird_function() {}
- fn random_method(&self) {}
- }
- }
-
- //- /main.rs crate:main deps:dep
- fn main() {
- dep::test_mod::TestStruct::spe$0
- }
- "#;
-
- check(
- fixture,
- expect![[r#"
- ct SPECIAL_CONST (use dep::test_mod::TestTrait)
- "#]],
- );
-
- check_edit(
- "SPECIAL_CONST",
- fixture,
- r#"
-use dep::test_mod::TestTrait;
-
-fn main() {
- dep::test_mod::TestStruct::SPECIAL_CONST
-}
-"#,
- );
- }
-
- #[test]
- fn trait_method_fuzzy_completion() {
- let fixture = r#"
- //- /lib.rs crate:dep
- pub mod test_mod {
- pub trait TestTrait {
- const SPECIAL_CONST: u8;
- type HumbleType;
- fn weird_function();
- fn random_method(&self);
- }
- pub struct TestStruct {}
- impl TestTrait for TestStruct {
- const SPECIAL_CONST: u8 = 42;
- type HumbleType = ();
- fn weird_function() {}
- fn random_method(&self) {}
- }
- }
-
- //- /main.rs crate:main deps:dep
- fn main() {
- let test_struct = dep::test_mod::TestStruct {};
- test_struct.ran$0
- }
- "#;
-
- check(
- fixture,
- expect![[r#"
- me random_method() (use dep::test_mod::TestTrait) fn(&self)
- "#]],
- );
-
- check_edit(
- "random_method",
- fixture,
- r#"
-use dep::test_mod::TestTrait;
-
-fn main() {
- let test_struct = dep::test_mod::TestStruct {};
- test_struct.random_method()$0
-}
-"#,
- );
- }
-
- #[test]
- fn no_trait_type_fuzzy_completion() {
- check(
- r#"
-//- /lib.rs crate:dep
-pub mod test_mod {
- pub trait TestTrait {
- const SPECIAL_CONST: u8;
- type HumbleType;
- fn weird_function();
- fn random_method(&self);
- }
- pub struct TestStruct {}
- impl TestTrait for TestStruct {
- const SPECIAL_CONST: u8 = 42;
- type HumbleType = ();
- fn weird_function() {}
- fn random_method(&self) {}
- }
-}
-
-//- /main.rs crate:main deps:dep
-fn main() {
- dep::test_mod::TestStruct::hum$0
-}
-"#,
- expect![[r#""#]],
- );
- }
-
- #[test]
- fn does_not_propose_names_in_scope() {
- check(
- r#"
-//- /lib.rs crate:dep
-pub mod test_mod {
- pub trait TestTrait {
- const SPECIAL_CONST: u8;
- type HumbleType;
- fn weird_function();
- fn random_method(&self);
- }
- pub struct TestStruct {}
- impl TestTrait for TestStruct {
- const SPECIAL_CONST: u8 = 42;
- type HumbleType = ();
- fn weird_function() {}
- fn random_method(&self) {}
- }
-}
-
-//- /main.rs crate:main deps:dep
-use dep::test_mod::TestStruct;
-fn main() {
- TestSt$0
-}
-"#,
- expect![[r#""#]],
- );
- }
-
- #[test]
- fn does_not_propose_traits_in_scope() {
- check(
- r#"
-//- /lib.rs crate:dep
-pub mod test_mod {
- pub trait TestTrait {
- const SPECIAL_CONST: u8;
- type HumbleType;
- fn weird_function();
- fn random_method(&self);
- }
- pub struct TestStruct {}
- impl TestTrait for TestStruct {
- const SPECIAL_CONST: u8 = 42;
- type HumbleType = ();
- fn weird_function() {}
- fn random_method(&self) {}
- }
-}
-
-//- /main.rs crate:main deps:dep
-use dep::test_mod::{TestStruct, TestTrait};
-fn main() {
- dep::test_mod::TestStruct::hum$0
-}
-"#,
- expect![[r#""#]],
- );
- }
-
- #[test]
- fn blanket_trait_impl_import() {
- check_edit(
- "another_function",
- r#"
-//- /lib.rs crate:dep
-pub mod test_mod {
- pub struct TestStruct {}
- pub trait TestTrait {
- fn another_function();
- }
- impl<T> TestTrait for T {
- fn another_function() {}
- }
-}
-
-//- /main.rs crate:main deps:dep
-fn main() {
- dep::test_mod::TestStruct::ano$0
-}
-"#,
- r#"
-use dep::test_mod::TestTrait;
-
-fn main() {
- dep::test_mod::TestStruct::another_function()$0
-}
-"#,
- );
- }
-
- #[test]
- fn zero_input_deprecated_assoc_item_completion() {
- check(
- r#"
-//- /lib.rs crate:dep
-pub mod test_mod {
- #[deprecated]
- pub trait TestTrait {
- const SPECIAL_CONST: u8;
- type HumbleType;
- fn weird_function();
- fn random_method(&self);
- }
- pub struct TestStruct {}
- impl TestTrait for TestStruct {
- const SPECIAL_CONST: u8 = 42;
- type HumbleType = ();
- fn weird_function() {}
- fn random_method(&self) {}
- }
-}
-
-//- /main.rs crate:main deps:dep
-fn main() {
- let test_struct = dep::test_mod::TestStruct {};
- test_struct.$0
-}
- "#,
- expect![[r#"
- me random_method() (use dep::test_mod::TestTrait) fn(&self) DEPRECATED
- "#]],
- );
-
- check(
- r#"
-//- /lib.rs crate:dep
-pub mod test_mod {
- #[deprecated]
- pub trait TestTrait {
- const SPECIAL_CONST: u8;
- type HumbleType;
- fn weird_function();
- fn random_method(&self);
- }
- pub struct TestStruct {}
- impl TestTrait for TestStruct {
- const SPECIAL_CONST: u8 = 42;
- type HumbleType = ();
- fn weird_function() {}
- fn random_method(&self) {}
- }
-}
-
-//- /main.rs crate:main deps:dep
-fn main() {
- dep::test_mod::TestStruct::$0
-}
-"#,
- expect![[r#"
- fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED
- ct SPECIAL_CONST (use dep::test_mod::TestTrait) DEPRECATED
- "#]],
- );
- }
-
- #[test]
- fn no_completions_in_use_statements() {
- check(
- r#"
-//- /lib.rs crate:dep
-pub mod io {
- pub fn stdin() {}
-};
-
-//- /main.rs crate:main deps:dep
-use stdi$0
-
-fn main() {}
-"#,
- expect![[]],
- );
- }
-
- #[test]
- fn prefix_config_usage() {
- let fixture = r#"
-mod foo {
- pub mod bar {
- pub struct Item;
- }
-}
-
-use crate::foo::bar;
-
-fn main() {
- Ite$0
-}"#;
- let mut config = TEST_CONFIG;
-
- config.insert_use.prefix_kind = hir::PrefixKind::ByCrate;
- check_edit_with_config(
- config.clone(),
- "Item",
- fixture,
- r#"
-mod foo {
- pub mod bar {
- pub struct Item;
- }
-}
-
-use crate::foo::bar::{self, Item};
-
-fn main() {
- Item
-}"#,
- );
-
- config.insert_use.prefix_kind = hir::PrefixKind::BySelf;
- check_edit_with_config(
- config.clone(),
- "Item",
- fixture,
- r#"
-mod foo {
- pub mod bar {
- pub struct Item;
- }
-}
-
-use crate::foo::bar;
-
-use self::foo::bar::Item;
-
-fn main() {
- Item
-}"#,
- );
-
- config.insert_use.prefix_kind = hir::PrefixKind::Plain;
- check_edit_with_config(
- config,
- "Item",
- fixture,
- r#"
-mod foo {
- pub mod bar {
- pub struct Item;
- }
-}
-
-use foo::bar::Item;
-
-use crate::foo::bar;
-
-fn main() {
- Item
-}"#,
- );
- }
-
- #[test]
- fn unresolved_qualifier() {
- let fixture = r#"
-mod foo {
- pub mod bar {
- pub mod baz {
- pub struct Item;
- }
- }
-}
-
-fn main() {
- bar::baz::Ite$0
-}"#;
-
- check(
- fixture,
- expect![[r#"
- st Item (use foo::bar::baz::Item)
- "#]],
- );
-
- check_edit(
- "Item",
- fixture,
- r#"
- use foo::bar;
-
- mod foo {
- pub mod bar {
- pub mod baz {
- pub struct Item;
- }
- }
- }
-
- fn main() {
- bar::baz::Item
- }"#,
- );
- }
-
- #[test]
- fn unresolved_assoc_item_container() {
- let fixture = r#"
-mod foo {
- pub struct Item;
-
- impl Item {
- pub const TEST_ASSOC: usize = 3;
- }
-}
-
-fn main() {
- Item::TEST_A$0
-}"#;
-
- check(
- fixture,
- expect![[r#"
- ct TEST_ASSOC (use foo::Item)
- "#]],
- );
-
- check_edit(
- "TEST_ASSOC",
- fixture,
- r#"
-use foo::Item;
-
-mod foo {
- pub struct Item;
-
- impl Item {
- pub const TEST_ASSOC: usize = 3;
- }
-}
-
-fn main() {
- Item::TEST_ASSOC
-}"#,
- );
- }
-
- #[test]
- fn unresolved_assoc_item_container_with_path() {
- let fixture = r#"
-mod foo {
- pub mod bar {
- pub struct Item;
-
- impl Item {
- pub const TEST_ASSOC: usize = 3;
- }
- }
-}
-
-fn main() {
- bar::Item::TEST_A$0
-}"#;
-
- check(
- fixture,
- expect![[r#"
- ct TEST_ASSOC (use foo::bar::Item)
- "#]],
- );
-
- check_edit(
- "TEST_ASSOC",
- fixture,
- r#"
-use foo::bar;
-
-mod foo {
- pub mod bar {
- pub struct Item;
-
- impl Item {
- pub const TEST_ASSOC: usize = 3;
- }
- }
-}
-
-fn main() {
- bar::Item::TEST_ASSOC
-}"#,
- );
- }
-
- #[test]
- fn fuzzy_unresolved_path() {
- check(
- r#"
-mod foo {
- pub mod bar {
- pub struct Item;
-
- impl Item {
- pub const TEST_ASSOC: usize = 3;
- }
- }
-}
-
-fn main() {
- bar::ASS$0
-}"#,
- expect![[]],
- )
- }
-
- #[test]
- fn unqualified_assoc_items_are_omitted() {
- check(
- r#"
-mod something {
- pub trait BaseTrait {
- fn test_function() -> i32;
- }
-
- pub struct Item1;
- pub struct Item2;
-
- impl BaseTrait for Item1 {
- fn test_function() -> i32 {
- 1
- }
- }
-
- impl BaseTrait for Item2 {
- fn test_function() -> i32 {
- 2
- }
- }
-}
-
-fn main() {
- test_f$0
-}"#,
- expect![[]],
- )
- }
-
- #[test]
- fn case_matters() {
- check(
- r#"
-mod foo {
- pub const TEST_CONST: usize = 3;
- pub fn test_function() -> i32 {
- 4
- }
-}
-
-fn main() {
- TE$0
-}"#,
- expect![[r#"
- ct TEST_CONST (use foo::TEST_CONST)
- "#]],
- );
-
- check(
- r#"
-mod foo {
- pub const TEST_CONST: usize = 3;
- pub fn test_function() -> i32 {
- 4
- }
-}
-
-fn main() {
- te$0
-}"#,
- expect![[r#"
- ct TEST_CONST (use foo::TEST_CONST)
- fn test_function() (use foo::test_function) fn() -> i32
- "#]],
- );
-
- check(
- r#"
-mod foo {
- pub const TEST_CONST: usize = 3;
- pub fn test_function() -> i32 {
- 4
- }
-}
-
-fn main() {
- Te$0
-}"#,
- expect![[]],
- );
- }
-
- #[test]
- fn no_fuzzy_during_fields_of_record_lit_syntax() {
- check(
- r#"
-mod m {
- pub fn some_fn() -> i32 {
- 42
- }
-}
-struct Foo {
- some_field: i32,
-}
-fn main() {
- let _ = Foo { so$0 };
-}
-"#,
- expect![[]],
- );
- }
-
- #[test]
- fn fuzzy_after_fields_of_record_lit_syntax() {
- check(
- r#"
-mod m {
- pub fn some_fn() -> i32 {
- 42
- }
-}
-struct Foo {
- some_field: i32,
-}
-fn main() {
- let _ = Foo { some_field: so$0 };
-}
-"#,
- expect![[r#"
- fn some_fn() (use m::some_fn) fn() -> i32
- "#]],
- );
- }
-
- #[test]
- fn no_flyimports_in_traits_and_impl_declarations() {
- check(
- r#"
-mod m {
- pub fn some_fn() -> i32 {
- 42
- }
-}
-trait Foo {
- som$0
-}
-"#,
- expect![[r#""#]],
- );
-
- check(
- r#"
-mod m {
- pub fn some_fn() -> i32 {
- 42
- }
-}
-struct Foo;
-impl Foo {
- som$0
-}
-"#,
- expect![[r#""#]],
- );
-
- check(
- r#"
-mod m {
- pub fn some_fn() -> i32 {
- 42
- }
-}
-struct Foo;
-trait Bar {}
-impl Bar for Foo {
- som$0
-}
-"#,
- expect![[r#""#]],
- );
- }
-
- #[test]
- fn no_inherent_candidates_proposed() {
- check(
- r#"
-mod baz {
- pub trait DefDatabase {
- fn method1(&self);
- }
- pub trait HirDatabase: DefDatabase {
- fn method2(&self);
- }
-}
-
-mod bar {
- fn test(db: &dyn crate::baz::HirDatabase) {
- db.metho$0
- }
-}
- "#,
- expect![[r#""#]],
- );
- }
-
- #[test]
- fn respects_doc_hidden() {
- check(
- r#"
-//- /lib.rs crate:lib deps:dep
-fn f() {
- ().fro$0
-}
-
-//- /dep.rs crate:dep
-#[doc(hidden)]
-pub trait Private {
- fn frob(&self) {}
-}
-
-impl<T> Private for T {}
- "#,
- expect![[r#""#]],
- );
- check(
- r#"
-//- /lib.rs crate:lib deps:dep
-fn f() {
- ().fro$0
-}
-
-//- /dep.rs crate:dep
-pub trait Private {
- #[doc(hidden)]
- fn frob(&self) {}
-}
-
-impl<T> Private for T {}
- "#,
- expect![[r#""#]],
- );
- }
-
- #[test]
- fn regression_9760() {
- check(
- r#"
-struct Struct;
-fn main() {}
-
-mod mud {
- fn func() {
- let struct_instance = Stru$0
- }
-}
-"#,
- expect![[r#"
- st Struct (use crate::Struct)
- "#]],
- );
- }
-
- #[test]
- fn flyimport_pattern() {
- check(
- r#"
-mod module {
- pub struct Struct;
-}
-fn function() {
- let Str$0
-}
-"#,
- expect![[r#"
- st Struct (use module::Struct)
- "#]],
- );
- }
-
- #[test]
- fn flyimport_rename() {
- check(
- r#"
-mod module {
- pub struct Struct;
-}
-use self as Str$0;
- "#,
- expect![[r#""#]],
- );
- }
-}
diff --git a/crates/ide_completion/src/completions/fn_param.rs b/crates/ide_completion/src/completions/fn_param.rs
index a9f1944e28..e910c1daaa 100644
--- a/crates/ide_completion/src/completions/fn_param.rs
+++ b/crates/ide_completion/src/completions/fn_param.rs
@@ -8,7 +8,7 @@ use syntax::{
use crate::{
context::{ParamKind, PatternContext},
- CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions,
+ CompletionContext, CompletionItem, CompletionItemKind, Completions,
};
/// Complete repeated parameters, both name and type. For example, if all
@@ -75,7 +75,7 @@ fn add_new_item_to_acc(
label: String,
lookup: String,
) {
- let mut item = CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label);
- item.kind(CompletionItemKind::Binding).lookup_by(lookup);
+ let mut item = CompletionItem::new(CompletionItemKind::Binding, ctx.source_range(), label);
+ item.lookup_by(lookup);
item.add_to(acc)
}
diff --git a/crates/ide_completion/src/completions/keyword.rs b/crates/ide_completion/src/completions/keyword.rs
index 31aabd98d3..afb8df2911 100644
--- a/crates/ide_completion/src/completions/keyword.rs
+++ b/crates/ide_completion/src/completions/keyword.rs
@@ -6,7 +6,7 @@ use syntax::{SyntaxKind, T};
use crate::{
context::PathCompletionContext, patterns::ImmediateLocation, CompletionContext, CompletionItem,
- CompletionItemKind, CompletionKind, Completions,
+ CompletionItemKind, Completions,
};
pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
@@ -158,8 +158,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
}
fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet: &str) {
- let mut item = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), kw);
- item.kind(CompletionItemKind::Keyword);
+ let mut item = CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw);
match ctx.config.snippet_cap {
Some(cap) => {
@@ -181,115 +180,15 @@ fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet
mod tests {
use expect_test::{expect, Expect};
- use crate::{
- tests::{check_edit, filtered_completion_list},
- CompletionKind,
- };
+ use crate::tests::{check_edit, completion_list};
fn check(ra_fixture: &str, expect: Expect) {
- let actual = filtered_completion_list(ra_fixture, CompletionKind::Keyword);
+ let actual = completion_list(ra_fixture);
expect.assert_eq(&actual)
}
#[test]
- fn test_keywords_in_function() {
- check(
- r"fn quux() { $0 }",
- expect![[r#"
- kw unsafe
- kw fn
- kw const
- kw type
- kw impl
- kw extern
- kw use
- kw trait
- kw static
- kw mod
- kw match
- kw while
- kw while let
- kw loop
- kw if
- kw if let
- kw for
- kw true
- kw false
- kw let
- kw return
- kw self
- kw super
- kw crate
- "#]],
- );
- }
-
- #[test]
- fn test_keywords_inside_block() {
- check(
- r"fn quux() { if true { $0 } }",
- expect![[r#"
- kw unsafe
- kw fn
- kw const
- kw type
- kw impl
- kw extern
- kw use
- kw trait
- kw static
- kw mod
- kw match
- kw while
- kw while let
- kw loop
- kw if
- kw if let
- kw for
- kw true
- kw false
- kw let
- kw return
- kw self
- kw super
- kw crate
- "#]],
- );
- }
-
- #[test]
- fn test_keywords_after_if() {
- check(
- r#"fn quux() { if true { () } $0 }"#,
- expect![[r#"
- kw unsafe
- kw fn
- kw const
- kw type
- kw impl
- kw extern
- kw use
- kw trait
- kw static
- kw mod
- kw match
- kw while
- kw while let
- kw loop
- kw if
- kw if let
- kw for
- kw true
- kw false
- kw let
- kw else
- kw else if
- kw return
- kw self
- kw super
- kw crate
- "#]],
- );
+ fn test_else_edit_after_if() {
check_edit(
"else",
r#"fn quux() { if true { () } $0 }"#,
@@ -300,68 +199,6 @@ mod tests {
}
#[test]
- fn test_keywords_in_match_arm() {
- check(
- r#"
-fn quux() -> i32 {
- match () { () => $0 }
-}
-"#,
- expect![[r#"
- kw unsafe
- kw match
- kw while
- kw while let
- kw loop
- kw if
- kw if let
- kw for
- kw true
- kw false
- kw return
- kw self
- kw super
- kw crate
- "#]],
- );
- }
-
- #[test]
- fn test_keywords_in_loop() {
- check(
- r"fn my() { loop { $0 } }",
- expect![[r#"
- kw unsafe
- kw fn
- kw const
- kw type
- kw impl
- kw extern
- kw use
- kw trait
- kw static
- kw mod
- kw match
- kw while
- kw while let
- kw loop
- kw if
- kw if let
- kw for
- kw true
- kw false
- kw let
- kw continue
- kw break
- kw return
- kw self
- kw super
- kw crate
- "#]],
- );
- }
-
- #[test]
fn test_keywords_after_unsafe_in_block_expr() {
check(
r"fn my_fn() { unsafe $0 }",
@@ -369,39 +206,13 @@ fn quux() -> i32 {
kw fn
kw trait
kw impl
+ sn pd
+ sn ppd
"#]],
);
}
#[test]
- fn no_keyword_completion_in_comments() {
- cov_mark::check!(no_keyword_completion_in_comments);
- check(
- r#"
-fn test() {
- let x = 2; // A comment$0
-}
-"#,
- expect![[""]],
- );
- check(
- r#"
-/*
-Some multi-line comment$0
-*/
-"#,
- expect![[""]],
- );
- check(
- r#"
-/// Some doc comment
-/// let test$0 = 1
-"#,
- expect![[""]],
- );
- }
-
- #[test]
fn test_completion_await_impls_future() {
check(
r#"
@@ -413,6 +224,18 @@ fn foo(a: A) { a.$0 }
"#,
expect![[r#"
kw await expr.await
+ sn ref &expr
+ sn refm &mut expr
+ sn match match expr {}
+ sn box Box::new(expr)
+ sn ok Ok(expr)
+ sn err Err(expr)
+ sn some Some(expr)
+ sn dbg dbg!(expr)
+ sn dbgr dbg!(&expr)
+ sn call function(expr)
+ sn let let
+ sn letm let mut
"#]],
);
@@ -427,84 +250,23 @@ fn foo() {
"#,
expect![[r#"
kw await expr.await
+ sn ref &expr
+ sn refm &mut expr
+ sn match match expr {}
+ sn box Box::new(expr)
+ sn ok Ok(expr)
+ sn err Err(expr)
+ sn some Some(expr)
+ sn dbg dbg!(expr)
+ sn dbgr dbg!(&expr)
+ sn call function(expr)
+ sn let let
+ sn letm let mut
"#]],
)
}
#[test]
- fn after_let() {
- check(
- r#"fn main() { let _ = $0 }"#,
- expect![[r#"
- kw unsafe
- kw match
- kw while
- kw while let
- kw loop
- kw if
- kw if let
- kw for
- kw true
- kw false
- kw return
- kw self
- kw super
- kw crate
- "#]],
- )
- }
-
- #[test]
- fn skip_struct_initializer() {
- cov_mark::check!(no_keyword_completion_in_record_lit);
- check(
- r#"
-struct Foo {
- pub f: i32,
-}
-fn foo() {
- Foo {
- $0
- }
-}
-"#,
- expect![[r#""#]],
- );
- }
-
- #[test]
- fn struct_initializer_field_expr() {
- check(
- r#"
-struct Foo {
- pub f: i32,
-}
-fn foo() {
- Foo {
- f: $0
- }
-}
-"#,
- expect![[r#"
- kw unsafe
- kw match
- kw while
- kw while let
- kw loop
- kw if
- kw if let
- kw for
- kw true
- kw false
- kw return
- kw self
- kw super
- kw crate
- "#]],
- );
- }
-
- #[test]
fn let_semi() {
cov_mark::check!(let_semi);
check_edit(
diff --git a/crates/ide_completion/src/completions/mod_.rs b/crates/ide_completion/src/completions/mod_.rs
index 1c864c0e70..28be83f196 100644
--- a/crates/ide_completion/src/completions/mod_.rs
+++ b/crates/ide_completion/src/completions/mod_.rs
@@ -11,7 +11,7 @@ use rustc_hash::FxHashSet;
use crate::{patterns::ImmediateLocation, CompletionItem};
-use crate::{context::CompletionContext, item::CompletionKind, Completions};
+use crate::{context::CompletionContext, Completions};
/// Complete mod declaration, i.e. `mod $0 ;`
pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
@@ -80,8 +80,7 @@ pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Op
if mod_under_caret.semicolon_token().is_none() {
label.push(';');
}
- let mut item = CompletionItem::new(CompletionKind::Magic, ctx.source_range(), &label);
- item.kind(SymbolKind::Module);
+ let item = CompletionItem::new(SymbolKind::Module, ctx.source_range(), &label);
item.add_to(acc)
});
@@ -141,9 +140,10 @@ fn module_chain_to_containing_module_file(
#[cfg(test)]
mod tests {
- use crate::tests::completion_list;
use expect_test::{expect, Expect};
+ use crate::tests::completion_list;
+
fn check(ra_fixture: &str, expect: Expect) {
let actual = completion_list(ra_fixture);
expect.assert_eq(&actual);
diff --git a/crates/ide_completion/src/completions/postfix.rs b/crates/ide_completion/src/completions/postfix.rs
index 4ace346768..4ee257ab43 100644
--- a/crates/ide_completion/src/completions/postfix.rs
+++ b/crates/ide_completion/src/completions/postfix.rs
@@ -15,11 +15,9 @@ use syntax::{
use text_edit::TextEdit;
use crate::{
- completions::postfix::format_like::add_format_like_completions,
- context::CompletionContext,
- item::{Builder, CompletionKind},
- patterns::ImmediateLocation,
- CompletionItem, CompletionItemKind, CompletionRelevance, Completions, SnippetScope,
+ completions::postfix::format_like::add_format_like_completions, context::CompletionContext,
+ item::Builder, patterns::ImmediateLocation, CompletionItem, CompletionItemKind,
+ CompletionRelevance, Completions, SnippetScope,
};
pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
@@ -45,8 +43,9 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
// Suggest .await syntax for types that implement Future trait
if receiver_ty.impls_future(ctx.db) {
- let mut item = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await");
- item.kind(CompletionItemKind::Keyword).detail("expr.await");
+ let mut item =
+ CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), "await");
+ item.detail("expr.await");
item.add_to(acc);
}
@@ -224,8 +223,9 @@ fn build_postfix_snippet_builder<'ctx>(
) -> impl Fn(&str, &str, &str) -> Builder + 'ctx {
move |label, detail, snippet| {
let edit = TextEdit::replace(delete_range, snippet.to_string());
- let mut item = CompletionItem::new(CompletionKind::Postfix, ctx.source_range(), label);
- item.detail(detail).kind(CompletionItemKind::Snippet).snippet_edit(cap, edit);
+ let mut item =
+ CompletionItem::new(CompletionItemKind::Snippet, ctx.source_range(), label);
+ item.detail(detail).snippet_edit(cap, edit);
if ctx.original_token.text() == label {
let relevance =
CompletionRelevance { exact_postfix_snippet_match: true, ..Default::default() };
@@ -270,12 +270,12 @@ mod tests {
use expect_test::{expect, Expect};
use crate::{
- tests::{check_edit, check_edit_with_config, filtered_completion_list, TEST_CONFIG},
- CompletionConfig, CompletionKind, Snippet,
+ tests::{check_edit, check_edit_with_config, completion_list, TEST_CONFIG},
+ CompletionConfig, Snippet,
};
fn check(ra_fixture: &str, expect: Expect) {
- let actual = filtered_completion_list(ra_fixture, CompletionKind::Postfix);
+ let actual = completion_list(ra_fixture);
expect.assert_eq(&actual)
}
diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs
index f61baf184b..e9d39edc43 100644
--- a/crates/ide_completion/src/completions/qualified_path.rs
+++ b/crates/ide_completion/src/completions/qualified_path.rs
@@ -250,13 +250,10 @@ fn add_enum_variants(acc: &mut Completions, ctx: &CompletionContext, e: hir::Enu
mod tests {
use expect_test::{expect, Expect};
- use crate::{
- tests::{check_edit, filtered_completion_list},
- CompletionKind,
- };
+ use crate::tests::{check_edit, completion_list_no_kw};
fn check(ra_fixture: &str, expect: Expect) {
- let actual = filtered_completion_list(ra_fixture, CompletionKind::Reference);
+ let actual = completion_list_no_kw(ra_fixture);
expect.assert_eq(&actual);
}
diff --git a/crates/ide_completion/src/completions/record.rs b/crates/ide_completion/src/completions/record.rs
index 80132c2566..f0c81f66bc 100644
--- a/crates/ide_completion/src/completions/record.rs
+++ b/crates/ide_completion/src/completions/record.rs
@@ -3,8 +3,7 @@ use ide_db::{helpers::FamousDefs, SymbolKind};
use syntax::{ast::Expr, T};
use crate::{
- item::CompletionKind, patterns::ImmediateLocation, CompletionContext, CompletionItem,
- CompletionItemKind, Completions,
+ patterns::ImmediateLocation, CompletionContext, CompletionItem, CompletionItemKind, Completions,
};
pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
@@ -22,20 +21,17 @@ pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) ->
let missing_fields = ctx.sema.record_literal_missing_fields(record_expr);
if impl_default_trait && !missing_fields.is_empty() && ctx.path_qual().is_none() {
let completion_text = "..Default::default()";
- let mut item = CompletionItem::new(
- CompletionKind::Snippet,
- ctx.source_range(),
- completion_text,
- );
+ let mut item =
+ CompletionItem::new(SymbolKind::Field, ctx.source_range(), completion_text);
let completion_text =
completion_text.strip_prefix(ctx.token.text()).unwrap_or(completion_text);
- item.insert_text(completion_text).kind(SymbolKind::Field);
+ item.insert_text(completion_text);
item.add_to(acc);
}
if ctx.previous_token_is(T![.]) {
let mut item =
- CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), "..");
- item.insert_text(".").kind(CompletionItemKind::Snippet);
+ CompletionItem::new(CompletionItemKind::Snippet, ctx.source_range(), "..");
+ item.insert_text(".");
item.add_to(acc);
return None;
}
diff --git a/crates/ide_completion/src/completions/snippet.rs b/crates/ide_completion/src/completions/snippet.rs
index a0e5f56129..1840e780ed 100644
--- a/crates/ide_completion/src/completions/snippet.rs
+++ b/crates/ide_completion/src/completions/snippet.rs
@@ -6,12 +6,12 @@ use syntax::T;
use crate::{
context::PathCompletionContext, item::Builder, CompletionContext, CompletionItem,
- CompletionItemKind, CompletionKind, Completions, SnippetScope,
+ CompletionItemKind, Completions, SnippetScope,
};
fn snippet(ctx: &CompletionContext, cap: SnippetCap, label: &str, snippet: &str) -> Builder {
- let mut item = CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), label);
- item.insert_snippet(cap, snippet).kind(CompletionItemKind::Snippet);
+ let mut item = CompletionItem::new(CompletionItemKind::Snippet, ctx.source_range(), label);
+ item.insert_snippet(cap, snippet);
item
}
diff --git a/crates/ide_completion/src/completions/trait_impl.rs b/crates/ide_completion/src/completions/trait_impl.rs
index 31accd035f..fc6ef5839c 100644
--- a/crates/ide_completion/src/completions/trait_impl.rs
+++ b/crates/ide_completion/src/completions/trait_impl.rs
@@ -40,7 +40,7 @@ use syntax::{
};
use text_edit::TextEdit;
-use crate::{CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions};
+use crate::{CompletionContext, CompletionItem, CompletionItemKind, Completions};
#[derive(Debug, PartialEq, Eq)]
enum ImplCompletionKind {
@@ -141,14 +141,14 @@ fn add_function_impl(
format!("fn {}(..)", fn_name)
};
- let mut item = CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label);
- item.lookup_by(fn_name).set_documentation(func.docs(ctx.db));
-
let completion_kind = if func.self_param(ctx.db).is_some() {
CompletionItemKind::Method
} else {
CompletionItemKind::SymbolKind(SymbolKind::Function)
};
+ let mut item = CompletionItem::new(completion_kind, ctx.source_range(), label);
+ item.lookup_by(fn_name).set_documentation(func.docs(ctx.db));
+
let range = replacement_range(ctx, fn_def_node);
if let Some(source) = func.source(ctx.db) {
@@ -170,7 +170,6 @@ fn add_function_impl(
item.text_edit(TextEdit::replace(range, header));
}
};
- item.kind(completion_kind);
item.add_to(acc);
}
}
@@ -211,10 +210,9 @@ fn add_type_alias_impl(
let snippet = format!("type {} = ", alias_name);
let range = replacement_range(ctx, type_def_node);
- let mut item = CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone());
+ let mut item = CompletionItem::new(SymbolKind::TypeAlias, ctx.source_range(), snippet.clone());
item.text_edit(TextEdit::replace(range, snippet))
.lookup_by(alias_name)
- .kind(SymbolKind::TypeAlias)
.set_documentation(type_alias.docs(ctx.db));
item.add_to(acc);
}
@@ -241,10 +239,9 @@ fn add_const_impl(
let range = replacement_range(ctx, const_def_node);
let mut item =
- CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone());
+ CompletionItem::new(SymbolKind::Const, ctx.source_range(), snippet.clone());
item.text_edit(TextEdit::replace(range, snippet))
.lookup_by(const_name)
- .kind(SymbolKind::Const)
.set_documentation(const_.docs(ctx.db));
item.add_to(acc);
}
@@ -290,13 +287,10 @@ fn replacement_range(ctx: &CompletionContext, item: &SyntaxNode) -> TextRange {
mod tests {
use expect_test::{expect, Expect};
- use crate::{
- tests::{check_edit, filtered_completion_list},
- CompletionKind,
- };
+ use crate::tests::{check_edit, completion_list_no_kw};
fn check(ra_fixture: &str, expect: Expect) {
- let actual = filtered_completion_list(ra_fixture, CompletionKind::Magic);
+ let actual = completion_list_no_kw(ra_fixture);
expect.assert_eq(&actual)
}
@@ -313,7 +307,12 @@ impl Test for T {
}
}
",
- expect![[""]],
+ expect![[r#"
+ sp Self
+ tt Test
+ st T
+ bt u32
+ "#]],
);
check(
@@ -356,7 +355,7 @@ impl Test for T {
}
}
",
- expect![[""]],
+ expect![[r#""#]],
);
check(
@@ -368,7 +367,10 @@ impl Test for T {
fn test(t$0)
}
",
- expect![[""]],
+ expect![[r#"
+ sp Self
+ st T
+ "#]],
);
check(
@@ -380,7 +382,10 @@ impl Test for T {
fn test(f: fn $0)
}
",
- expect![[""]],
+ expect![[r#"
+ sp Self
+ st T
+ "#]],
);
}
@@ -395,7 +400,7 @@ impl Test for T {
const TEST: fn $0
}
",
- expect![[""]],
+ expect![[r#""#]],
);
check(
@@ -407,7 +412,12 @@ impl Test for T {
const TEST: T$0
}
",
- expect![[""]],
+ expect![[r#"
+ sp Self
+ tt Test
+ st T
+ bt u32
+ "#]],
);
check(
@@ -419,7 +429,12 @@ impl Test for T {
const TEST: u32 = f$0
}
",
- expect![[""]],
+ expect![[r#"
+ sp Self
+ tt Test
+ st T
+ bt u32
+ "#]],
);
check(
@@ -433,7 +448,12 @@ impl Test for T {
};
}
",
- expect![[""]],
+ expect![[r#"
+ sp Self
+ tt Test
+ st T
+ bt u32
+ "#]],
);
check(
@@ -476,7 +496,12 @@ impl Test for T {
type Test = T$0;
}
",
- expect![[""]],
+ expect![[r#"
+ sp Self
+ tt Test
+ st T
+ bt u32
+ "#]],
);
check(
@@ -488,7 +513,12 @@ impl Test for T {
type Test = fn $0;
}
",
- expect![[""]],
+ expect![[r#"
+ sp Self
+ tt Test
+ st T
+ bt u32
+ "#]],
);
}
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs
index afacf7fe03..825fae587b 100644
--- a/crates/ide_completion/src/completions/unqualified_path.rs
+++ b/crates/ide_completion/src/completions/unqualified_path.rs
@@ -117,24 +117,15 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
mod tests {
use expect_test::{expect, Expect};
- use crate::{
- tests::{check_edit, filtered_completion_list_with_config, TEST_CONFIG},
- CompletionConfig, CompletionKind,
- };
+ use crate::tests::{check_edit, completion_list_no_kw};
fn check(ra_fixture: &str, expect: Expect) {
- check_with_config(TEST_CONFIG, ra_fixture, expect);
- }
-
- fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) {
- let actual =
- filtered_completion_list_with_config(config, ra_fixture, CompletionKind::Reference);
+ let actual = completion_list_no_kw(ra_fixture);
expect.assert_eq(&actual)
}
#[test]
fn completes_if_prefix_is_keyword() {
- cov_mark::check!(completes_if_prefix_is_keyword);
check_edit(
"wherewolf",
r#"
@@ -188,6 +179,7 @@ pub mod prelude {
"#,
expect![[r#"
md std
+ bt u32
st Option
"#]],
);
@@ -217,6 +209,7 @@ mod macros {
fn f() fn()
ma concat!(…) #[macro_export] macro_rules! concat
md std
+ bt u32
"##]],
);
}
@@ -245,6 +238,7 @@ pub mod prelude {
expect![[r#"
md std
md core
+ bt u32
st String
"#]],
);
@@ -273,6 +267,7 @@ pub mod prelude {
expect![[r#"
fn f() fn()
md std
+ bt u32
"#]],
);
}
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index 4e3abff3b3..0cb484d507 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -134,7 +134,6 @@ impl<'a> CompletionContext<'a> {
// check kind of macro-expanded token, but use range of original token
let kind = self.token.kind();
if kind == IDENT || kind == LIFETIME_IDENT || kind == UNDERSCORE || kind.is_keyword() {
- cov_mark::hit!(completes_if_prefix_is_keyword);
self.original_token.text_range()
} else if kind == CHAR {
// assume we are completing a lifetime but the user has only typed the '
diff --git a/crates/ide_completion/src/item.rs b/crates/ide_completion/src/item.rs
index a9eec472ca..3f0accfbe1 100644
--- a/crates/ide_completion/src/item.rs
+++ b/crates/ide_completion/src/item.rs
@@ -21,10 +21,6 @@ use text_edit::TextEdit;
/// `CompletionItem`, use `new` method and the `Builder` struct.
#[derive(Clone)]
pub struct CompletionItem {
- /// Used only internally in tests, to check only specific kind of
- /// completion (postfix, keyword, reference, etc).
- #[allow(unused)]
- pub(crate) completion_kind: CompletionKind,
/// Label in the completion pop up which identifies completion.
label: String,
/// Range of identifier that is being completed.
@@ -43,7 +39,7 @@ pub struct CompletionItem {
is_snippet: bool,
/// What item (struct, function, etc) are we completing.
- kind: Option<CompletionItemKind>,
+ kind: CompletionItemKind,
/// Lookup is used to check if completion item indeed can complete current
/// ident.
@@ -92,9 +88,7 @@ impl fmt::Debug for CompletionItem {
} else {
s.field("text_edit", &self.text_edit);
}
- if let Some(kind) = self.kind().as_ref() {
- s.field("kind", kind);
- }
+ s.field("kind", &self.kind());
if self.lookup() != self.label() {
s.field("lookup", &self.lookup());
}
@@ -270,32 +264,15 @@ impl CompletionItemKind {
}
}
-// FIXME remove this?
-/// Like [`CompletionItemKind`] but solely used for filtering test results.
-#[derive(Debug, PartialEq, Eq, Copy, Clone)]
-pub(crate) enum CompletionKind {
- /// Parser-based keyword completion.
- Keyword,
- /// Your usual "complete all valid identifiers".
- Reference,
- /// "Secret sauce" completions.
- Magic,
- Snippet,
- Postfix,
- BuiltinType,
- Attribute,
-}
-
impl CompletionItem {
pub(crate) fn new(
- completion_kind: CompletionKind,
+ kind: impl Into<CompletionItemKind>,
source_range: TextRange,
label: impl Into<String>,
) -> Builder {
let label = label.into();
Builder {
source_range,
- completion_kind,
label,
insert_text: None,
is_snippet: false,
@@ -303,7 +280,7 @@ impl CompletionItem {
detail: None,
documentation: None,
lookup: None,
- kind: None,
+ kind: kind.into(),
text_edit: None,
deprecated: false,
trigger_call_info: None,
@@ -342,7 +319,7 @@ impl CompletionItem {
self.lookup.as_deref().unwrap_or(&self.label)
}
- pub fn kind(&self) -> Option<CompletionItemKind> {
+ pub fn kind(&self) -> CompletionItemKind {
self.kind
}
@@ -401,7 +378,6 @@ impl ImportEdit {
#[derive(Clone)]
pub(crate) struct Builder {
source_range: TextRange,
- completion_kind: CompletionKind,
imports_to_add: SmallVec<[ImportEdit; 1]>,
trait_name: Option<String>,
label: String,
@@ -410,7 +386,7 @@ pub(crate) struct Builder {
detail: Option<String>,
documentation: Option<Documentation>,
lookup: Option<String>,
- kind: Option<CompletionItemKind>,
+ kind: CompletionItemKind,
text_edit: Option<TextEdit>,
deprecated: bool,
trigger_call_info: Option<bool>,
@@ -454,7 +430,6 @@ impl Builder {
documentation: self.documentation,
lookup,
kind: self.kind,
- completion_kind: self.completion_kind,
deprecated: self.deprecated,
trigger_call_info: self.trigger_call_info.unwrap_or(false),
relevance: self.relevance,
@@ -487,10 +462,6 @@ impl Builder {
self.is_snippet = true;
self.insert_text(snippet)
}
- pub(crate) fn kind(&mut self, kind: impl Into<CompletionItemKind>) -> &mut Builder {
- self.kind = Some(kind.into());
- self
- }
pub(crate) fn text_edit(&mut self, edit: TextEdit) -> &mut Builder {
self.text_edit = Some(edit);
self
diff --git a/crates/ide_completion/src/lib.rs b/crates/ide_completion/src/lib.rs
index 6680e66c60..d555eff878 100644
--- a/crates/ide_completion/src/lib.rs
+++ b/crates/ide_completion/src/lib.rs
@@ -24,7 +24,7 @@ use ide_db::{
use syntax::algo;
use text_edit::TextEdit;
-use crate::{completions::Completions, context::CompletionContext, item::CompletionKind};
+use crate::{completions::Completions, context::CompletionContext};
pub use crate::{
config::CompletionConfig,
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]
diff --git a/crates/ide_completion/src/render/const_.rs b/crates/ide_completion/src/render/const_.rs
index 166ae3c16b..241e0043c9 100644
--- a/crates/ide_completion/src/render/const_.rs
+++ b/crates/ide_completion/src/render/const_.rs
@@ -7,10 +7,7 @@ use syntax::{
display::const_label,
};
-use crate::{
- item::{CompletionItem, CompletionKind},
- render::RenderContext,
-};
+use crate::{item::CompletionItem, render::RenderContext};
pub(crate) fn render_const(ctx: RenderContext<'_>, const_: hir::Const) -> Option<CompletionItem> {
ConstRender::new(ctx, const_)?.render()
@@ -34,9 +31,8 @@ impl<'a> ConstRender<'a> {
let detail = self.detail();
let mut item =
- CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), name.clone());
- item.kind(SymbolKind::Const)
- .set_documentation(self.ctx.docs(self.const_))
+ 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_),
diff --git a/crates/ide_completion/src/render/enum_variant.rs b/crates/ide_completion/src/render/enum_variant.rs
index 95768713cf..728e0e2a17 100644
--- a/crates/ide_completion/src/render/enum_variant.rs
+++ b/crates/ide_completion/src/render/enum_variant.rs
@@ -7,7 +7,7 @@ use ide_db::SymbolKind;
use itertools::Itertools;
use crate::{
- item::{CompletionItem, CompletionKind, ImportEdit},
+ item::{CompletionItem, ImportEdit},
render::{builder_ext::Params, compute_ref_match, compute_type_match, RenderContext},
CompletionRelevance,
};
@@ -61,12 +61,11 @@ impl<'a> EnumRender<'a> {
}
fn render(self, import_to_add: Option<ImportEdit>) -> CompletionItem {
let mut item = CompletionItem::new(
- CompletionKind::Reference,
+ SymbolKind::Variant,
self.ctx.source_range(),
self.qualified_name.to_string(),
);
- item.kind(SymbolKind::Variant)
- .set_documentation(self.variant.docs(self.ctx.db()))
+ item.set_documentation(self.variant.docs(self.ctx.db()))
.set_deprecated(self.ctx.is_deprecated(self.variant))
.detail(self.detail());
diff --git a/crates/ide_completion/src/render/function.rs b/crates/ide_completion/src/render/function.rs
index 769a0ed21f..7515bb6d47 100644
--- a/crates/ide_completion/src/render/function.rs
+++ b/crates/ide_completion/src/render/function.rs
@@ -7,7 +7,7 @@ use itertools::Itertools;
use syntax::ast;
use crate::{
- item::{CompletionItem, CompletionItemKind, CompletionKind, CompletionRelevance, ImportEdit},
+ item::{CompletionItem, CompletionItemKind, CompletionRelevance, ImportEdit},
render::{
builder_ext::Params, compute_exact_name_match, compute_ref_match, compute_type_match,
RenderContext,
@@ -79,10 +79,8 @@ impl<'a> FunctionRender<'a> {
Some(receiver) => format!("{}.{}", receiver, &self.name),
None => self.name.clone(),
};
- let mut item =
- CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), call.clone());
- item.kind(self.kind())
- .set_documentation(self.ctx.docs(self.func))
+ 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),
)
diff --git a/crates/ide_completion/src/render/macro_.rs b/crates/ide_completion/src/render/macro_.rs
index 196b667baa..b1ddfab0cb 100644
--- a/crates/ide_completion/src/render/macro_.rs
+++ b/crates/ide_completion/src/render/macro_.rs
@@ -6,7 +6,7 @@ use syntax::display::macro_label;
use crate::{
context::CallKind,
- item::{CompletionItem, CompletionKind, ImportEdit},
+ item::{CompletionItem, ImportEdit},
render::RenderContext,
};
@@ -47,9 +47,8 @@ impl<'a> MacroRender<'a> {
} else {
Some(self.ctx.source_range())
}?;
- let mut item = CompletionItem::new(CompletionKind::Reference, source_range, &self.label());
- item.kind(SymbolKind::Macro)
- .set_documentation(self.docs.clone())
+ let mut item = CompletionItem::new(SymbolKind::Macro, source_range, &self.label());
+ item.set_documentation(self.docs.clone())
.set_deprecated(self.ctx.is_deprecated(self.macro_))
.set_detail(self.detail());
diff --git a/crates/ide_completion/src/render/pattern.rs b/crates/ide_completion/src/render/pattern.rs
index 521296fd9b..b703280620 100644
--- a/crates/ide_completion/src/render/pattern.rs
+++ b/crates/ide_completion/src/render/pattern.rs
@@ -6,7 +6,6 @@ use itertools::Itertools;
use crate::{
context::{ParamKind, PatternContext},
- item::CompletionKind,
render::RenderContext,
CompletionItem, CompletionItemKind,
};
@@ -58,11 +57,8 @@ fn build_completion(
pat: String,
def: impl HasAttrs + Copy,
) -> CompletionItem {
- let mut item = CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), name);
- item.kind(CompletionItemKind::Binding)
- .set_documentation(ctx.docs(def))
- .set_deprecated(ctx.is_deprecated(def))
- .detail(&pat);
+ let mut item = CompletionItem::new(CompletionItemKind::Binding, ctx.source_range(), name);
+ item.set_documentation(ctx.docs(def)).set_deprecated(ctx.is_deprecated(def)).detail(&pat);
match ctx.snippet_cap() {
Some(snippet_cap) => item.insert_snippet(snippet_cap, pat),
None => item.insert_text(pat),
diff --git a/crates/ide_completion/src/render/struct_literal.rs b/crates/ide_completion/src/render/struct_literal.rs
index 810b51effd..4eb4f6b9f1 100644
--- a/crates/ide_completion/src/render/struct_literal.rs
+++ b/crates/ide_completion/src/render/struct_literal.rs
@@ -4,7 +4,7 @@ use hir::{db::HirDatabase, HasAttrs, HasVisibility, Name, StructKind};
use ide_db::helpers::SnippetCap;
use itertools::Itertools;
-use crate::{item::CompletionKind, render::RenderContext, CompletionItem, CompletionItemKind};
+use crate::{render::RenderContext, CompletionItem, CompletionItemKind};
pub(crate) fn render_struct_literal(
ctx: RenderContext<'_>,
@@ -33,11 +33,9 @@ fn build_completion(
literal: String,
def: impl HasAttrs + Copy,
) -> CompletionItem {
- let mut item = CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), name + " {…}");
- item.kind(CompletionItemKind::Snippet)
- .set_documentation(ctx.docs(def))
- .set_deprecated(ctx.is_deprecated(def))
- .detail(&literal);
+ let mut item =
+ CompletionItem::new(CompletionItemKind::Snippet, ctx.source_range(), name + " {…}");
+ item.set_documentation(ctx.docs(def)).set_deprecated(ctx.is_deprecated(def)).detail(&literal);
match ctx.snippet_cap() {
Some(snippet_cap) => item.insert_snippet(snippet_cap, literal),
None => item.insert_text(literal),
diff --git a/crates/ide_completion/src/render/type_alias.rs b/crates/ide_completion/src/render/type_alias.rs
index c1e6182643..7b6d2fa5c3 100644
--- a/crates/ide_completion/src/render/type_alias.rs
+++ b/crates/ide_completion/src/render/type_alias.rs
@@ -7,10 +7,7 @@ use syntax::{
display::type_label,
};
-use crate::{
- item::{CompletionItem, CompletionKind},
- render::RenderContext,
-};
+use crate::{item::CompletionItem, render::RenderContext};
pub(crate) fn render_type_alias(
ctx: RenderContext<'_>,
@@ -50,9 +47,8 @@ impl<'a> TypeAliasRender<'a> {
let detail = self.detail();
let mut item =
- CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), name.clone());
- item.kind(SymbolKind::TypeAlias)
- .set_documentation(self.ctx.docs(self.type_alias))
+ 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),
diff --git a/crates/ide_completion/src/tests.rs b/crates/ide_completion/src/tests.rs
index 4028fc2242..f063a9638c 100644
--- a/crates/ide_completion/src/tests.rs
+++ b/crates/ide_completion/src/tests.rs
@@ -20,6 +20,7 @@ mod record;
mod type_pos;
mod use_tree;
mod visibility;
+mod flyimport;
use std::mem;
@@ -37,7 +38,7 @@ use stdx::{format_to, trim_indent};
use syntax::{AstNode, NodeOrToken, SyntaxElement};
use test_utils::assert_eq_text;
-use crate::{item::CompletionKind, CompletionConfig, CompletionItem};
+use crate::{CompletionConfig, CompletionItem, CompletionItemKind};
/// Lots of basic item definitions
const BASE_ITEMS_FIXTURE: &str = r#"
@@ -77,18 +78,28 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
};
pub(crate) fn completion_list(ra_fixture: &str) -> String {
- completion_list_with_config(TEST_CONFIG, ra_fixture)
+ completion_list_with_config(TEST_CONFIG, ra_fixture, true)
}
-fn completion_list_with_config(config: CompletionConfig, ra_fixture: &str) -> String {
+pub(crate) fn completion_list_no_kw(ra_fixture: &str) -> String {
+ completion_list_with_config(TEST_CONFIG, ra_fixture, false)
+}
+
+fn completion_list_with_config(
+ config: CompletionConfig,
+ ra_fixture: &str,
+ include_keywords: bool,
+) -> String {
// filter out all but one builtintype completion for smaller test outputs
let items = get_all_items(config, ra_fixture);
let mut bt_seen = false;
let items = items
.into_iter()
.filter(|it| {
- it.completion_kind != CompletionKind::BuiltinType || !mem::replace(&mut bt_seen, true)
+ it.kind() != CompletionItemKind::BuiltinType || !mem::replace(&mut bt_seen, true)
})
+ .filter(|it| include_keywords || it.kind() != CompletionItemKind::Keyword)
+ .filter(|it| include_keywords || it.kind() != CompletionItemKind::Snippet)
.collect();
render_completion_list(items)
}
@@ -104,36 +115,22 @@ pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) {
(database, FilePosition { file_id, offset })
}
-pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> {
+pub(crate) fn do_completion(code: &str, kind: CompletionItemKind) -> Vec<CompletionItem> {
do_completion_with_config(TEST_CONFIG, code, kind)
}
pub(crate) fn do_completion_with_config(
config: CompletionConfig,
code: &str,
- kind: CompletionKind,
+ kind: CompletionItemKind,
) -> Vec<CompletionItem> {
get_all_items(config, code)
.into_iter()
- .filter(|c| c.completion_kind == kind)
+ .filter(|c| c.kind() == kind)
.sorted_by(|l, r| l.label().cmp(r.label()))
.collect()
}
-pub(crate) fn filtered_completion_list(code: &str, kind: CompletionKind) -> String {
- filtered_completion_list_with_config(TEST_CONFIG, code, kind)
-}
-
-pub(crate) fn filtered_completion_list_with_config(
- config: CompletionConfig,
- code: &str,
- kind: CompletionKind,
-) -> String {
- let kind_completions: Vec<CompletionItem> =
- get_all_items(config, code).into_iter().filter(|c| c.completion_kind == kind).collect();
- render_completion_list(kind_completions)
-}
-
fn render_completion_list(completions: Vec<CompletionItem>) -> String {
fn monospace_width(s: &str) -> usize {
s.chars().count()
@@ -143,7 +140,7 @@ fn render_completion_list(completions: Vec<CompletionItem>) -> String {
completions
.into_iter()
.map(|it| {
- let tag = it.kind().unwrap().tag();
+ let tag = it.kind().tag();
let var_name = format!("{} {}", tag, it.label());
let mut buf = var_name;
if let Some(detail) = it.detail() {
@@ -254,3 +251,37 @@ fn foo() {
"#,
);
}
+
+#[test]
+fn no_completions_in_comments() {
+ cov_mark::check!(no_keyword_completion_in_comments);
+ assert_eq!(
+ completion_list(
+ r#"
+fn test() {
+let x = 2; // A comment$0
+}
+"#,
+ ),
+ String::new(),
+ );
+ assert_eq!(
+ completion_list(
+ r#"
+/*
+Some multi-line comment$0
+*/
+"#,
+ ),
+ String::new(),
+ );
+ assert_eq!(
+ completion_list(
+ r#"
+/// Some doc comment
+/// let test$0 = 1
+"#,
+ ),
+ String::new(),
+ );
+}
diff --git a/crates/ide_completion/src/tests/expression.rs b/crates/ide_completion/src/tests/expression.rs
index 9a42dd7b27..a634808734 100644
--- a/crates/ide_completion/src/tests/expression.rs
+++ b/crates/ide_completion/src/tests/expression.rs
@@ -110,7 +110,7 @@ fn func(param0 @ (param1, param2): (i32, i32)) {
}
#[test]
-fn completes_all_the_things() {
+fn completes_all_the_things_in_fn_body() {
cov_mark::check!(unqualified_skip_lifetime_completion);
check(
r#"
@@ -207,6 +207,223 @@ impl Unit {
}
#[test]
+fn complete_in_block() {
+ check_empty(
+ r#"
+ fn foo() {
+ if true {
+ $0
+ }
+ }
+"#,
+ expect![[r#"
+ kw unsafe
+ kw fn
+ kw const
+ kw type
+ kw impl
+ kw extern
+ kw use
+ kw trait
+ kw static
+ kw mod
+ kw match
+ kw while
+ kw while let
+ kw loop
+ kw if
+ kw if let
+ kw for
+ kw true
+ kw false
+ kw let
+ kw return
+ sn pd
+ sn ppd
+ kw self
+ kw super
+ kw crate
+ fn foo() fn()
+ bt u32
+ "#]],
+ )
+}
+
+#[test]
+fn complete_after_if_expr() {
+ check_empty(
+ r#"
+ fn foo() {
+ if true {}
+ $0
+ }
+"#,
+ expect![[r#"
+ kw unsafe
+ kw fn
+ kw const
+ kw type
+ kw impl
+ kw extern
+ kw use
+ kw trait
+ kw static
+ kw mod
+ kw match
+ kw while
+ kw while let
+ kw loop
+ kw if
+ kw if let
+ kw for
+ kw true
+ kw false
+ kw let
+ kw else
+ kw else if
+ kw return
+ sn pd
+ sn ppd
+ kw self
+ kw super
+ kw crate
+ fn foo() fn()
+ bt u32
+ "#]],
+ )
+}
+
+#[test]
+fn complete_in_match_arm() {
+ check_empty(
+ r#"
+ fn foo() {
+ match () {
+ () => $0
+ }
+ }
+"#,
+ expect![[r#"
+ kw unsafe
+ kw match
+ kw while
+ kw while let
+ kw loop
+ kw if
+ kw if let
+ kw for
+ kw true
+ kw false
+ kw return
+ kw self
+ kw super
+ kw crate
+ fn foo() fn()
+ bt u32
+ "#]],
+ )
+}
+
+#[test]
+fn completes_in_loop_ctx() {
+ check_empty(
+ r"fn my() { loop { $0 } }",
+ expect![[r#"
+ kw unsafe
+ kw fn
+ kw const
+ kw type
+ kw impl
+ kw extern
+ kw use
+ kw trait
+ kw static
+ kw mod
+ kw match
+ kw while
+ kw while let
+ kw loop
+ kw if
+ kw if let
+ kw for
+ kw true
+ kw false
+ kw let
+ kw continue
+ kw break
+ kw return
+ sn pd
+ sn ppd
+ kw self
+ kw super
+ kw crate
+ fn my() fn()
+ bt u32
+ "#]],
+ );
+}
+
+#[test]
+fn completes_in_let_initializer() {
+ check_empty(
+ r#"fn main() { let _ = $0 }"#,
+ expect![[r#"
+ kw unsafe
+ kw match
+ kw while
+ kw while let
+ kw loop
+ kw if
+ kw if let
+ kw for
+ kw true
+ kw false
+ kw return
+ kw self
+ kw super
+ kw crate
+ fn main() fn()
+ bt u32
+ "#]],
+ )
+}
+
+#[test]
+fn struct_initializer_field_expr() {
+ check_empty(
+ r#"
+struct Foo {
+ pub f: i32,
+}
+fn foo() {
+ Foo {
+ f: $0
+ }
+}
+"#,
+ expect![[r#"
+ kw unsafe
+ kw match
+ kw while
+ kw while let
+ kw loop
+ kw if
+ kw if let
+ kw for
+ kw true
+ kw false
+ kw return
+ kw self
+ kw super
+ kw crate
+ st Foo
+ fn foo() fn()
+ bt u32
+ "#]],
+ );
+}
+
+#[test]
fn shadowing_shows_single_completion() {
cov_mark::check!(shadowing_shows_single_completion);
diff --git a/crates/ide_completion/src/tests/flyimport.rs b/crates/ide_completion/src/tests/flyimport.rs
new file mode 100644
index 0000000000..201443e10c
--- /dev/null
+++ b/crates/ide_completion/src/tests/flyimport.rs
@@ -0,0 +1,1014 @@
+use expect_test::{expect, Expect};
+
+use crate::tests::{check_edit, check_edit_with_config, TEST_CONFIG};
+
+fn check(ra_fixture: &str, expect: Expect) {
+ let config = TEST_CONFIG;
+ let (db, position) = crate::tests::position(ra_fixture);
+ let ctx = crate::context::CompletionContext::new(&db, position, &config).unwrap();
+
+ let mut acc = crate::completions::Completions::default();
+ crate::completions::flyimport::import_on_the_fly(&mut acc, &ctx);
+
+ expect.assert_eq(&super::render_completion_list(Vec::from(acc)));
+}
+
+#[test]
+fn function_fuzzy_completion() {
+ check_edit(
+ "stdin",
+ r#"
+//- /lib.rs crate:dep
+pub mod io {
+ pub fn stdin() {}
+};
+
+//- /main.rs crate:main deps:dep
+fn main() {
+ stdi$0
+}
+"#,
+ r#"
+use dep::io::stdin;
+
+fn main() {
+ stdin()$0
+}
+"#,
+ );
+}
+
+#[test]
+fn macro_fuzzy_completion() {
+ check_edit(
+ "macro_with_curlies!",
+ r#"
+//- /lib.rs crate:dep
+/// Please call me as macro_with_curlies! {}
+#[macro_export]
+macro_rules! macro_with_curlies {
+ () => {}
+}
+
+//- /main.rs crate:main deps:dep
+fn main() {
+ curli$0
+}
+"#,
+ r#"
+use dep::macro_with_curlies;
+
+fn main() {
+ macro_with_curlies! {$0}
+}
+"#,
+ );
+}
+
+#[test]
+fn struct_fuzzy_completion() {
+ check_edit(
+ "ThirdStruct",
+ r#"
+//- /lib.rs crate:dep
+pub struct FirstStruct;
+pub mod some_module {
+ pub struct SecondStruct;
+ pub struct ThirdStruct;
+}
+
+//- /main.rs crate:main deps:dep
+use dep::{FirstStruct, some_module::SecondStruct};
+
+fn main() {
+ this$0
+}
+"#,
+ r#"
+use dep::{FirstStruct, some_module::{SecondStruct, ThirdStruct}};
+
+fn main() {
+ ThirdStruct
+}
+"#,
+ );
+}
+
+#[test]
+fn short_paths_are_ignored() {
+ cov_mark::check!(ignore_short_input_for_path);
+
+ check(
+ r#"
+//- /lib.rs crate:dep
+pub struct FirstStruct;
+pub mod some_module {
+ pub struct SecondStruct;
+ pub struct ThirdStruct;
+}
+
+//- /main.rs crate:main deps:dep
+use dep::{FirstStruct, some_module::SecondStruct};
+
+fn main() {
+ t$0
+}
+"#,
+ expect![[r#""#]],
+ );
+}
+
+#[test]
+fn fuzzy_completions_come_in_specific_order() {
+ cov_mark::check!(certain_fuzzy_order_test);
+ check(
+ r#"
+//- /lib.rs crate:dep
+pub struct FirstStruct;
+pub mod some_module {
+ // already imported, omitted
+ pub struct SecondStruct;
+ // does not contain all letters from the query, omitted
+ pub struct UnrelatedOne;
+ // contains all letters from the query, but not in sequence, displayed last
+ pub struct ThiiiiiirdStruct;
+ // contains all letters from the query, but not in the beginning, displayed second
+ pub struct AfterThirdStruct;
+ // contains all letters from the query in the begginning, displayed first
+ pub struct ThirdStruct;
+}
+
+//- /main.rs crate:main deps:dep
+use dep::{FirstStruct, some_module::SecondStruct};
+
+fn main() {
+ hir$0
+}
+"#,
+ expect![[r#"
+ st ThirdStruct (use dep::some_module::ThirdStruct)
+ st AfterThirdStruct (use dep::some_module::AfterThirdStruct)
+ st ThiiiiiirdStruct (use dep::some_module::ThiiiiiirdStruct)
+ "#]],
+ );
+}
+
+#[test]
+fn trait_function_fuzzy_completion() {
+ let fixture = r#"
+ //- /lib.rs crate:dep
+ pub mod test_mod {
+ pub trait TestTrait {
+ const SPECIAL_CONST: u8;
+ type HumbleType;
+ fn weird_function();
+ fn random_method(&self);
+ }
+ pub struct TestStruct {}
+ impl TestTrait for TestStruct {
+ const SPECIAL_CONST: u8 = 42;
+ type HumbleType = ();
+ fn weird_function() {}
+ fn random_method(&self) {}
+ }
+ }
+
+ //- /main.rs crate:main deps:dep
+ fn main() {
+ dep::test_mod::TestStruct::wei$0
+ }
+ "#;
+
+ check(
+ fixture,
+ expect![[r#"
+ fn weird_function() (use dep::test_mod::TestTrait) fn()
+ "#]],
+ );
+
+ check_edit(
+ "weird_function",
+ fixture,
+ r#"
+use dep::test_mod::TestTrait;
+
+fn main() {
+ dep::test_mod::TestStruct::weird_function()$0
+}
+"#,
+ );
+}
+
+#[test]
+fn trait_const_fuzzy_completion() {
+ let fixture = r#"
+ //- /lib.rs crate:dep
+ pub mod test_mod {
+ pub trait TestTrait {
+ const SPECIAL_CONST: u8;
+ type HumbleType;
+ fn weird_function();
+ fn random_method(&self);
+ }
+ pub struct TestStruct {}
+ impl TestTrait for TestStruct {
+ const SPECIAL_CONST: u8 = 42;
+ type HumbleType = ();
+ fn weird_function() {}
+ fn random_method(&self) {}
+ }
+ }
+
+ //- /main.rs crate:main deps:dep
+ fn main() {
+ dep::test_mod::TestStruct::spe$0
+ }
+ "#;
+
+ check(
+ fixture,
+ expect![[r#"
+ ct SPECIAL_CONST (use dep::test_mod::TestTrait)
+ "#]],
+ );
+
+ check_edit(
+ "SPECIAL_CONST",
+ fixture,
+ r#"
+use dep::test_mod::TestTrait;
+
+fn main() {
+ dep::test_mod::TestStruct::SPECIAL_CONST
+}
+"#,
+ );
+}
+
+#[test]
+fn trait_method_fuzzy_completion() {
+ let fixture = r#"
+ //- /lib.rs crate:dep
+ pub mod test_mod {
+ pub trait TestTrait {
+ const SPECIAL_CONST: u8;
+ type HumbleType;
+ fn weird_function();
+ fn random_method(&self);
+ }
+ pub struct TestStruct {}
+ impl TestTrait for TestStruct {
+ const SPECIAL_CONST: u8 = 42;
+ type HumbleType = ();
+ fn weird_function() {}
+ fn random_method(&self) {}
+ }
+ }
+
+ //- /main.rs crate:main deps:dep
+ fn main() {
+ let test_struct = dep::test_mod::TestStruct {};
+ test_struct.ran$0
+ }
+ "#;
+
+ check(
+ fixture,
+ expect![[r#"
+ me random_method() (use dep::test_mod::TestTrait) fn(&self)
+ "#]],
+ );
+
+ check_edit(
+ "random_method",
+ fixture,
+ r#"
+use dep::test_mod::TestTrait;
+
+fn main() {
+ let test_struct = dep::test_mod::TestStruct {};
+ test_struct.random_method()$0
+}
+"#,
+ );
+}
+
+#[test]
+fn no_trait_type_fuzzy_completion() {
+ check(
+ r#"
+//- /lib.rs crate:dep
+pub mod test_mod {
+ pub trait TestTrait {
+ const SPECIAL_CONST: u8;
+ type HumbleType;
+ fn weird_function();
+ fn random_method(&self);
+ }
+ pub struct TestStruct {}
+ impl TestTrait for TestStruct {
+ const SPECIAL_CONST: u8 = 42;
+ type HumbleType = ();
+ fn weird_function() {}
+ fn random_method(&self) {}
+ }
+}
+
+//- /main.rs crate:main deps:dep
+fn main() {
+ dep::test_mod::TestStruct::hum$0
+}
+"#,
+ expect![[r#""#]],
+ );
+}
+
+#[test]
+fn does_not_propose_names_in_scope() {
+ check(
+ r#"
+//- /lib.rs crate:dep
+pub mod test_mod {
+ pub trait TestTrait {
+ const SPECIAL_CONST: u8;
+ type HumbleType;
+ fn weird_function();
+ fn random_method(&self);
+ }
+ pub struct TestStruct {}
+ impl TestTrait for TestStruct {
+ const SPECIAL_CONST: u8 = 42;
+ type HumbleType = ();
+ fn weird_function() {}
+ fn random_method(&self) {}
+ }
+}
+
+//- /main.rs crate:main deps:dep
+use dep::test_mod::TestStruct;
+fn main() {
+ TestSt$0
+}
+"#,
+ expect![[r#""#]],
+ );
+}
+
+#[test]
+fn does_not_propose_traits_in_scope() {
+ check(
+ r#"
+//- /lib.rs crate:dep
+pub mod test_mod {
+ pub trait TestTrait {
+ const SPECIAL_CONST: u8;
+ type HumbleType;
+ fn weird_function();
+ fn random_method(&self);
+ }
+ pub struct TestStruct {}
+ impl TestTrait for TestStruct {
+ const SPECIAL_CONST: u8 = 42;
+ type HumbleType = ();
+ fn weird_function() {}
+ fn random_method(&self) {}
+ }
+}
+
+//- /main.rs crate:main deps:dep
+use dep::test_mod::{TestStruct, TestTrait};
+fn main() {
+ dep::test_mod::TestStruct::hum$0
+}
+"#,
+ expect![[r#""#]],
+ );
+}
+
+#[test]
+fn blanket_trait_impl_import() {
+ check_edit(
+ "another_function",
+ r#"
+//- /lib.rs crate:dep
+pub mod test_mod {
+ pub struct TestStruct {}
+ pub trait TestTrait {
+ fn another_function();
+ }
+ impl<T> TestTrait for T {
+ fn another_function() {}
+ }
+}
+
+//- /main.rs crate:main deps:dep
+fn main() {
+ dep::test_mod::TestStruct::ano$0
+}
+"#,
+ r#"
+use dep::test_mod::TestTrait;
+
+fn main() {
+ dep::test_mod::TestStruct::another_function()$0
+}
+"#,
+ );
+}
+
+#[test]
+fn zero_input_deprecated_assoc_item_completion() {
+ check(
+ r#"
+//- /lib.rs crate:dep
+pub mod test_mod {
+ #[deprecated]
+ pub trait TestTrait {
+ const SPECIAL_CONST: u8;
+ type HumbleType;
+ fn weird_function();
+ fn random_method(&self);
+ }
+ pub struct TestStruct {}
+ impl TestTrait for TestStruct {
+ const SPECIAL_CONST: u8 = 42;
+ type HumbleType = ();
+ fn weird_function() {}
+ fn random_method(&self) {}
+ }
+}
+
+//- /main.rs crate:main deps:dep
+fn main() {
+ let test_struct = dep::test_mod::TestStruct {};
+ test_struct.$0
+}
+ "#,
+ expect![[r#"
+ me random_method() (use dep::test_mod::TestTrait) fn(&self) DEPRECATED
+ "#]],
+ );
+
+ check(
+ r#"
+//- /lib.rs crate:dep
+pub mod test_mod {
+ #[deprecated]
+ pub trait TestTrait {
+ const SPECIAL_CONST: u8;
+ type HumbleType;
+ fn weird_function();
+ fn random_method(&self);
+ }
+ pub struct TestStruct {}
+ impl TestTrait for TestStruct {
+ const SPECIAL_CONST: u8 = 42;
+ type HumbleType = ();
+ fn weird_function() {}
+ fn random_method(&self) {}
+ }
+}
+
+//- /main.rs crate:main deps:dep
+fn main() {
+ dep::test_mod::TestStruct::$0
+}
+"#,
+ expect![[r#"
+ fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED
+ ct SPECIAL_CONST (use dep::test_mod::TestTrait) DEPRECATED
+ "#]],
+ );
+}
+
+#[test]
+fn no_completions_in_use_statements() {
+ check(
+ r#"
+//- /lib.rs crate:dep
+pub mod io {
+ pub fn stdin() {}
+};
+
+//- /main.rs crate:main deps:dep
+use stdi$0
+
+fn main() {}
+"#,
+ expect![[]],
+ );
+}
+
+#[test]
+fn prefix_config_usage() {
+ let fixture = r#"
+mod foo {
+ pub mod bar {
+ pub struct Item;
+ }
+}
+
+use crate::foo::bar;
+
+fn main() {
+ Ite$0
+}"#;
+ let mut config = TEST_CONFIG;
+
+ config.insert_use.prefix_kind = hir::PrefixKind::ByCrate;
+ check_edit_with_config(
+ config.clone(),
+ "Item",
+ fixture,
+ r#"
+mod foo {
+ pub mod bar {
+ pub struct Item;
+ }
+}
+
+use crate::foo::bar::{self, Item};
+
+fn main() {
+ Item
+}"#,
+ );
+
+ config.insert_use.prefix_kind = hir::PrefixKind::BySelf;
+ check_edit_with_config(
+ config.clone(),
+ "Item",
+ fixture,
+ r#"
+mod foo {
+ pub mod bar {
+ pub struct Item;
+ }
+}
+
+use crate::foo::bar;
+
+use self::foo::bar::Item;
+
+fn main() {
+ Item
+}"#,
+ );
+
+ config.insert_use.prefix_kind = hir::PrefixKind::Plain;
+ check_edit_with_config(
+ config,
+ "Item",
+ fixture,
+ r#"
+mod foo {
+ pub mod bar {
+ pub struct Item;
+ }
+}
+
+use foo::bar::Item;
+
+use crate::foo::bar;
+
+fn main() {
+ Item
+}"#,
+ );
+}
+
+#[test]
+fn unresolved_qualifier() {
+ let fixture = r#"
+mod foo {
+ pub mod bar {
+ pub mod baz {
+ pub struct Item;
+ }
+ }
+}
+
+fn main() {
+ bar::baz::Ite$0
+}"#;
+
+ check(
+ fixture,
+ expect![[r#"
+ st Item (use foo::bar::baz::Item)
+ "#]],
+ );
+
+ check_edit(
+ "Item",
+ fixture,
+ r#"
+ use foo::bar;
+
+ mod foo {
+ pub mod bar {
+ pub mod baz {
+ pub struct Item;
+ }
+ }
+ }
+
+ fn main() {
+ bar::baz::Item
+ }"#,
+ );
+}
+
+#[test]
+fn unresolved_assoc_item_container() {
+ let fixture = r#"
+mod foo {
+ pub struct Item;
+
+ impl Item {
+ pub const TEST_ASSOC: usize = 3;
+ }
+}
+
+fn main() {
+ Item::TEST_A$0
+}"#;
+
+ check(
+ fixture,
+ expect![[r#"
+ ct TEST_ASSOC (use foo::Item)
+ "#]],
+ );
+
+ check_edit(
+ "TEST_ASSOC",
+ fixture,
+ r#"
+use foo::Item;
+
+mod foo {
+ pub struct Item;
+
+ impl Item {
+ pub const TEST_ASSOC: usize = 3;
+ }
+}
+
+fn main() {
+ Item::TEST_ASSOC
+}"#,
+ );
+}
+
+#[test]
+fn unresolved_assoc_item_container_with_path() {
+ let fixture = r#"
+mod foo {
+ pub mod bar {
+ pub struct Item;
+
+ impl Item {
+ pub const TEST_ASSOC: usize = 3;
+ }
+ }
+}
+
+fn main() {
+ bar::Item::TEST_A$0
+}"#;
+
+ check(
+ fixture,
+ expect![[r#"
+ ct TEST_ASSOC (use foo::bar::Item)
+ "#]],
+ );
+
+ check_edit(
+ "TEST_ASSOC",
+ fixture,
+ r#"
+use foo::bar;
+
+mod foo {
+ pub mod bar {
+ pub struct Item;
+
+ impl Item {
+ pub const TEST_ASSOC: usize = 3;
+ }
+ }
+}
+
+fn main() {
+ bar::Item::TEST_ASSOC
+}"#,
+ );
+}
+
+#[test]
+fn fuzzy_unresolved_path() {
+ check(
+ r#"
+mod foo {
+ pub mod bar {
+ pub struct Item;
+
+ impl Item {
+ pub const TEST_ASSOC: usize = 3;
+ }
+ }
+}
+
+fn main() {
+ bar::ASS$0
+}"#,
+ expect![[]],
+ )
+}
+
+#[test]
+fn unqualified_assoc_items_are_omitted() {
+ check(
+ r#"
+mod something {
+ pub trait BaseTrait {
+ fn test_function() -> i32;
+ }
+
+ pub struct Item1;
+ pub struct Item2;
+
+ impl BaseTrait for Item1 {
+ fn test_function() -> i32 {
+ 1
+ }
+ }
+
+ impl BaseTrait for Item2 {
+ fn test_function() -> i32 {
+ 2
+ }
+ }
+}
+
+fn main() {
+ test_f$0
+}"#,
+ expect![[]],
+ )
+}
+
+#[test]
+fn case_matters() {
+ check(
+ r#"
+mod foo {
+ pub const TEST_CONST: usize = 3;
+ pub fn test_function() -> i32 {
+ 4
+ }
+}
+
+fn main() {
+ TE$0
+}"#,
+ expect![[r#"
+ ct TEST_CONST (use foo::TEST_CONST)
+ "#]],
+ );
+
+ check(
+ r#"
+mod foo {
+ pub const TEST_CONST: usize = 3;
+ pub fn test_function() -> i32 {
+ 4
+ }
+}
+
+fn main() {
+ te$0
+}"#,
+ expect![[r#"
+ ct TEST_CONST (use foo::TEST_CONST)
+ fn test_function() (use foo::test_function) fn() -> i32
+ "#]],
+ );
+
+ check(
+ r#"
+mod foo {
+ pub const TEST_CONST: usize = 3;
+ pub fn test_function() -> i32 {
+ 4
+ }
+}
+
+fn main() {
+ Te$0
+}"#,
+ expect![[]],
+ );
+}
+
+#[test]
+fn no_fuzzy_during_fields_of_record_lit_syntax() {
+ check(
+ r#"
+mod m {
+ pub fn some_fn() -> i32 {
+ 42
+ }
+}
+struct Foo {
+ some_field: i32,
+}
+fn main() {
+ let _ = Foo { so$0 };
+}
+"#,
+ expect![[]],
+ );
+}
+
+#[test]
+fn fuzzy_after_fields_of_record_lit_syntax() {
+ check(
+ r#"
+mod m {
+ pub fn some_fn() -> i32 {
+ 42
+ }
+}
+struct Foo {
+ some_field: i32,
+}
+fn main() {
+ let _ = Foo { some_field: so$0 };
+}
+"#,
+ expect![[r#"
+ fn some_fn() (use m::some_fn) fn() -> i32
+ "#]],
+ );
+}
+
+#[test]
+fn no_flyimports_in_traits_and_impl_declarations() {
+ check(
+ r#"
+mod m {
+ pub fn some_fn() -> i32 {
+ 42
+ }
+}
+trait Foo {
+ som$0
+}
+"#,
+ expect![[r#""#]],
+ );
+
+ check(
+ r#"
+mod m {
+ pub fn some_fn() -> i32 {
+ 42
+ }
+}
+struct Foo;
+impl Foo {
+ som$0
+}
+"#,
+ expect![[r#""#]],
+ );
+
+ check(
+ r#"
+mod m {
+ pub fn some_fn() -> i32 {
+ 42
+ }
+}
+struct Foo;
+trait Bar {}
+impl Bar for Foo {
+ som$0
+}
+"#,
+ expect![[r#""#]],
+ );
+}
+
+#[test]
+fn no_inherent_candidates_proposed() {
+ check(
+ r#"
+mod baz {
+ pub trait DefDatabase {
+ fn method1(&self);
+ }
+ pub trait HirDatabase: DefDatabase {
+ fn method2(&self);
+ }
+}
+
+mod bar {
+ fn test(db: &dyn crate::baz::HirDatabase) {
+ db.metho$0
+ }
+}
+ "#,
+ expect![[r#""#]],
+ );
+}
+
+#[test]
+fn respects_doc_hidden() {
+ check(
+ r#"
+//- /lib.rs crate:lib deps:dep
+fn f() {
+ ().fro$0
+}
+
+//- /dep.rs crate:dep
+#[doc(hidden)]
+pub trait Private {
+ fn frob(&self) {}
+}
+
+impl<T> Private for T {}
+ "#,
+ expect![[r#""#]],
+ );
+ check(
+ r#"
+//- /lib.rs crate:lib deps:dep
+fn f() {
+ ().fro$0
+}
+
+//- /dep.rs crate:dep
+pub trait Private {
+ #[doc(hidden)]
+ fn frob(&self) {}
+}
+
+impl<T> Private for T {}
+ "#,
+ expect![[r#""#]],
+ );
+}
+
+#[test]
+fn regression_9760() {
+ check(
+ r#"
+struct Struct;
+fn main() {}
+
+mod mud {
+ fn func() {
+ let struct_instance = Stru$0
+ }
+}
+"#,
+ expect![[r#"
+ st Struct (use crate::Struct)
+ "#]],
+ );
+}
+
+#[test]
+fn flyimport_pattern() {
+ check(
+ r#"
+mod module {
+ pub struct Struct;
+}
+fn function() {
+ let Str$0
+}
+"#,
+ expect![[r#"
+ st Struct (use module::Struct)
+ "#]],
+ );
+}
+
+#[test]
+fn flyimport_rename() {
+ check(
+ r#"
+mod module {
+ pub struct Struct;
+}
+use self as Str$0;
+ "#,
+ expect![[r#""#]],
+ );
+}
diff --git a/crates/ide_completion/src/tests/record.rs b/crates/ide_completion/src/tests/record.rs
index 30b1f2c1c9..e09e99aad5 100644
--- a/crates/ide_completion/src/tests/record.rs
+++ b/crates/ide_completion/src/tests/record.rs
@@ -9,6 +9,7 @@ fn check(ra_fixture: &str, expect: Expect) {
#[test]
fn without_default_impl() {
+ cov_mark::check!(no_keyword_completion_in_record_lit);
check(
r#"
struct Struct { foo: u32, bar: usize }
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index b17711d6a6..473b7a870f 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -248,7 +248,7 @@ fn completion_item(
label: item.label().to_string(),
detail: item.detail().map(|it| it.to_string()),
filter_text: Some(item.lookup().to_string()),
- kind: item.kind().map(completion_item_kind),
+ kind: Some(completion_item_kind(item.kind())),
text_edit: Some(text_edit),
additional_text_edits: Some(additional_text_edits),
documentation: item.documentation().map(documentation),
diff --git a/crates/rust-analyzer/tests/slow-tests/tidy.rs b/crates/rust-analyzer/tests/slow-tests/tidy.rs
index 9be9f3afea..5debb9fb3d 100644
--- a/crates/rust-analyzer/tests/slow-tests/tidy.rs
+++ b/crates/rust-analyzer/tests/slow-tests/tidy.rs
@@ -313,6 +313,7 @@ fn check_dbg(path: &Path, text: &str) {
"handlers/remove_dbg.rs",
// We have .dbg postfix
"ide_completion/src/completions/postfix.rs",
+ "ide_completion/src/completions/keyword.rs",
"ide_completion/src/tests/proc_macros.rs",
// The documentation in string literals may contain anything for its own purposes
"ide_completion/src/lib.rs",