summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/ide-completion
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/rust-analyzer/crates/ide-completion')
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs181
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs33
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs30
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/record.rs25
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/config.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/item.rs34
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/lib.rs25
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render.rs522
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs87
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests.rs21
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs252
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs126
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs24
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs33
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/predicate.rs42
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/record.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs270
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs486
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/use_tree.rs20
25 files changed, 1700 insertions, 531 deletions
diff --git a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
index 092fb3036..60f90a41b 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
@@ -13,7 +13,7 @@ doctest = false
[dependencies]
cov-mark = "2.0.0-pre.1"
-itertools = "0.10.5"
+itertools.workspace = true
once_cell = "1.17.0"
smallvec.workspace = true
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs
index f60ac1501..7d38c638a 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs
@@ -626,6 +626,7 @@ fn enum_variants_with_paths(
ctx.db,
hir::ModuleDef::from(variant),
ctx.config.prefer_no_std,
+ ctx.config.prefer_prelude,
) {
// Variants with trivial paths are already added by the existing completion logic,
// so we should avoid adding these twice
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs
index c5bbb7f8d..613a35dcb 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs
@@ -26,17 +26,17 @@ pub(crate) fn complete_dot(
item.add_to(acc, ctx.db);
}
- if let DotAccessKind::Method { .. } = dot_access.kind {
- cov_mark::hit!(test_no_struct_field_completion_for_method_call);
- } else {
- complete_fields(
- acc,
- ctx,
- receiver_ty,
- |acc, field, ty| acc.add_field(ctx, dot_access, None, field, &ty),
- |acc, field, ty| acc.add_tuple_field(ctx, None, field, &ty),
- );
- }
+ let is_field_access = matches!(dot_access.kind, DotAccessKind::Field { .. });
+
+ complete_fields(
+ acc,
+ ctx,
+ receiver_ty,
+ |acc, field, ty| acc.add_field(ctx, dot_access, None, field, &ty),
+ |acc, field, ty| acc.add_tuple_field(ctx, None, field, &ty),
+ is_field_access,
+ );
+
complete_methods(ctx, receiver_ty, |func| acc.add_method(ctx, dot_access, func, None, None));
}
@@ -82,6 +82,7 @@ pub(crate) fn complete_undotted_self(
)
},
|acc, field, ty| acc.add_tuple_field(ctx, Some(hir::known::SELF_PARAM), field, &ty),
+ true,
);
complete_methods(ctx, &ty, |func| {
acc.add_method(
@@ -104,18 +105,23 @@ fn complete_fields(
receiver: &hir::Type,
mut named_field: impl FnMut(&mut Completions, hir::Field, hir::Type),
mut tuple_index: impl FnMut(&mut Completions, usize, hir::Type),
+ is_field_access: bool,
) {
let mut seen_names = FxHashSet::default();
for receiver in receiver.autoderef(ctx.db) {
for (field, ty) in receiver.fields(ctx.db) {
- if seen_names.insert(field.name(ctx.db)) {
+ if seen_names.insert(field.name(ctx.db))
+ && (is_field_access || ty.is_fn() || ty.is_closure())
+ {
named_field(acc, field, ty);
}
}
for (i, ty) in receiver.tuple_fields(ctx.db).into_iter().enumerate() {
// Tuples are always the last type in a deref chain, so just check if the name is
// already seen without inserting into the hashset.
- if !seen_names.contains(&hir::Name::new_tuple_field(i)) {
+ if !seen_names.contains(&hir::Name::new_tuple_field(i))
+ && (is_field_access || ty.is_fn() || ty.is_closure())
+ {
// Tuple fields are always public (tuple struct fields are handled above).
tuple_index(acc, i, ty);
}
@@ -250,7 +256,6 @@ impl A {
#[test]
fn test_no_struct_field_completion_for_method_call() {
- cov_mark::check!(test_no_struct_field_completion_for_method_call);
check(
r#"
struct A { the_field: u32 }
@@ -935,9 +940,9 @@ impl Foo { fn foo(&self) { $0 } }"#,
expect![[r#"
fd self.field i32
lc self &Foo
- sp Self
- st Foo
- bt u32
+ sp Self Foo
+ st Foo Foo
+ bt u32 u32
me self.foo() fn(&self)
"#]],
);
@@ -949,9 +954,9 @@ impl Foo { fn foo(&mut self) { $0 } }"#,
expect![[r#"
fd self.0 i32
lc self &mut Foo
- sp Self
- st Foo
- bt u32
+ sp Self Foo
+ st Foo Foo
+ bt u32 u32
me self.foo() fn(&mut self)
"#]],
);
@@ -1095,4 +1100,140 @@ fn test(s: S<Unknown>) {
"#]],
);
}
+
+ #[test]
+ fn assoc_impl_1() {
+ check(
+ r#"
+//- minicore: deref
+fn main() {
+ let foo: Foo<&u8> = Foo::new(&42_u8);
+ foo.$0
+}
+
+trait Bar {
+ fn bar(&self);
+}
+
+impl Bar for u8 {
+ fn bar(&self) {}
+}
+
+struct Foo<F> {
+ foo: F,
+}
+
+impl<F> Foo<F> {
+ fn new(foo: F) -> Foo<F> {
+ Foo { foo }
+ }
+}
+
+impl<F: core::ops::Deref<Target = impl Bar>> Foo<F> {
+ fn foobar(&self) {
+ self.foo.deref().bar()
+ }
+}
+"#,
+ expect![[r#"
+ fd foo &u8
+ me foobar() fn(&self)
+ "#]],
+ );
+ }
+
+ #[test]
+ fn assoc_impl_2() {
+ check(
+ r#"
+//- minicore: deref
+fn main() {
+ let foo: Foo<&u8> = Foo::new(&42_u8);
+ foo.$0
+}
+
+trait Bar {
+ fn bar(&self);
+}
+
+struct Foo<F> {
+ foo: F,
+}
+
+impl<F> Foo<F> {
+ fn new(foo: F) -> Foo<F> {
+ Foo { foo }
+ }
+}
+
+impl<B: Bar, F: core::ops::Deref<Target = B>> Foo<F> {
+ fn foobar(&self) {
+ self.foo.deref().bar()
+ }
+}
+"#,
+ expect![[r#"
+ fd foo &u8
+ "#]],
+ );
+ }
+
+ #[test]
+ fn test_struct_function_field_completion() {
+ check(
+ r#"
+struct S { va_field: u32, fn_field: fn() }
+fn foo() { S { va_field: 0, fn_field: || {} }.fi$0() }
+"#,
+ expect![[r#"
+ fd fn_field fn()
+ "#]],
+ );
+
+ check_edit(
+ "fn_field",
+ r#"
+struct S { va_field: u32, fn_field: fn() }
+fn foo() { S { va_field: 0, fn_field: || {} }.fi$0() }
+"#,
+ r#"
+struct S { va_field: u32, fn_field: fn() }
+fn foo() { (S { va_field: 0, fn_field: || {} }.fn_field)() }
+"#,
+ );
+ }
+
+ #[test]
+ fn test_tuple_function_field_completion() {
+ check(
+ r#"
+struct B(u32, fn())
+fn foo() {
+ let b = B(0, || {});
+ b.$0()
+}
+"#,
+ expect![[r#"
+ fd 1 fn()
+ "#]],
+ );
+
+ check_edit(
+ "1",
+ r#"
+struct B(u32, fn())
+fn foo() {
+ let b = B(0, || {});
+ b.$0()
+}
+"#,
+ r#"
+struct B(u32, fn())
+fn foo() {
+ let b = B(0, || {});
+ (b.1)()
+}
+"#,
+ )
+ }
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
index 9daa6984c..d3c817d4b 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
@@ -175,6 +175,7 @@ pub(crate) fn complete_expr_path(
ctx.db,
hir::ModuleDef::from(strukt),
ctx.config.prefer_no_std,
+ ctx.config.prefer_prelude,
)
.filter(|it| it.len() > 1);
@@ -197,6 +198,7 @@ pub(crate) fn complete_expr_path(
ctx.db,
hir::ModuleDef::from(un),
ctx.config.prefer_no_std,
+ ctx.config.prefer_prelude,
)
.filter(|it| it.len() > 1);
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs
index 39c1b7f7b..d74d3b264 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs
@@ -13,10 +13,9 @@ use crate::{
TypeLocation,
},
render::{render_resolution_with_import, render_resolution_with_import_pat, RenderContext},
+ Completions,
};
-use super::Completions;
-
// Feature: Completion With Autoimport
//
// When completing names in the current scope, proposes additional imports from other modules or crates,
@@ -258,7 +257,12 @@ fn import_on_the_fly(
let user_input_lowercased = potential_import_name.to_lowercase();
import_assets
- .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind, ctx.config.prefer_no_std)
+ .search_for_imports(
+ &ctx.sema,
+ ctx.config.insert_use.prefix_kind,
+ ctx.config.prefer_no_std,
+ ctx.config.prefer_prelude,
+ )
.into_iter()
.filter(ns_filter)
.filter(|import| {
@@ -300,7 +304,12 @@ fn import_on_the_fly_pat_(
let user_input_lowercased = potential_import_name.to_lowercase();
import_assets
- .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind, ctx.config.prefer_no_std)
+ .search_for_imports(
+ &ctx.sema,
+ ctx.config.insert_use.prefix_kind,
+ ctx.config.prefer_no_std,
+ ctx.config.prefer_prelude,
+ )
.into_iter()
.filter(ns_filter)
.filter(|import| {
@@ -337,7 +346,12 @@ fn import_on_the_fly_method(
let user_input_lowercased = potential_import_name.to_lowercase();
import_assets
- .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind, ctx.config.prefer_no_std)
+ .search_for_imports(
+ &ctx.sema,
+ ctx.config.insert_use.prefix_kind,
+ ctx.config.prefer_no_std,
+ ctx.config.prefer_prelude,
+ )
.into_iter()
.filter(|import| {
!ctx.is_item_hidden(&import.item_to_import)
@@ -377,9 +391,12 @@ fn import_assets_for_path(
&ctx.sema,
ctx.token.parent()?,
)?;
- if fuzzy_name_length < 3 {
- cov_mark::hit!(flyimport_exact_on_short_path);
- assets_for_path.path_fuzzy_name_to_exact(false);
+ if fuzzy_name_length == 0 {
+ // nothing matches the empty string exactly, but we still compute assoc items in this case
+ assets_for_path.path_fuzzy_name_to_exact();
+ } else if fuzzy_name_length < 3 {
+ cov_mark::hit!(flyimport_prefix_on_short_path);
+ assets_for_path.path_fuzzy_name_to_prefix();
}
Some(assets_for_path)
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
index 42dfbfc7d..b0e4d8a5a 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
@@ -417,10 +417,10 @@ impl Test for T {
}
",
expect![[r#"
- sp Self
- st T
+ sp Self T
+ st T T
tt Test
- bt u32
+ bt u32 u32
"#]],
);
@@ -526,10 +526,10 @@ impl Test for T {
}
",
expect![[r#"
- sp Self
- st T
+ sp Self T
+ st T T
tt Test
- bt u32
+ bt u32 u32
"#]],
);
@@ -543,10 +543,10 @@ impl Test for T {
}
",
expect![[r#"
- sp Self
- st T
+ sp Self T
+ st T T
tt Test
- bt u32
+ bt u32 u32
"#]],
);
@@ -562,10 +562,10 @@ impl Test for T {
}
",
expect![[r#"
- sp Self
- st T
+ sp Self T
+ st T T
tt Test
- bt u32
+ bt u32 u32
"#]],
);
@@ -610,10 +610,10 @@ impl Test for T {
}
",
expect![[r#"
- sp Self
- st T
+ sp Self T
+ st T T
tt Test
- bt u32
+ bt u32 u32
"#]],
);
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs
index 1e0989405..5d138eea4 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs
@@ -2,7 +2,7 @@
use std::iter;
-use hir::{Module, ModuleSource};
+use hir::{HirFileIdExt, Module, ModuleSource};
use ide_db::{
base_db::{SourceDatabaseExt, VfsPath},
FxHashSet, RootDatabase, SymbolKind,
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/record.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/record.rs
index 945c3945b..46213deb0 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/record.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/record.rs
@@ -430,4 +430,29 @@ fn foo() {
"#,
);
}
+
+ #[test]
+ fn callable_field_struct_init() {
+ check_edit(
+ "field",
+ r#"
+struct S {
+ field: fn(),
+}
+
+fn main() {
+ S {fi$0
+}
+"#,
+ r#"
+struct S {
+ field: fn(),
+}
+
+fn main() {
+ S {field
+}
+"#,
+ );
+ }
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs
index 7a60030e9..81107c1f4 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs
@@ -71,9 +71,9 @@ pub(crate) fn complete_use_path(
if add_resolution {
let mut builder = Builder::from_resolution(ctx, path_ctx, name, def);
- builder.set_relevance(CompletionRelevance {
+ builder.with_relevance(|r| CompletionRelevance {
is_name_already_imported,
- ..Default::default()
+ ..r
});
acc.add(builder.build(ctx.db));
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/config.rs b/src/tools/rust-analyzer/crates/ide-completion/src/config.rs
index 8f6a97e1e..ed5ddde8f 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/config.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/config.rs
@@ -14,10 +14,12 @@ pub struct CompletionConfig {
pub enable_imports_on_the_fly: bool,
pub enable_self_on_the_fly: bool,
pub enable_private_editable: bool,
+ pub full_function_signatures: bool,
pub callable: Option<CallableSnippets>,
pub snippet_cap: Option<SnippetCap>,
pub insert_use: InsertUseConfig,
pub prefer_no_std: bool,
+ pub prefer_prelude: bool,
pub snippets: Vec<Snippet>,
pub limit: Option<usize>,
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
index c45cc8d7b..de41a5bd7 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
@@ -1,6 +1,6 @@
//! See `CompletionItem` structure.
-use std::fmt;
+use std::{fmt, mem};
use hir::Mutability;
use ide_db::{
@@ -26,6 +26,10 @@ use crate::{
pub struct CompletionItem {
/// Label in the completion pop up which identifies completion.
pub label: SmolStr,
+ /// Additional label details in the completion pop up that are
+ /// displayed and aligned on the right side after the label.
+ pub label_detail: Option<SmolStr>,
+
/// Range of identifier that is being completed.
///
/// It should be used primarily for UI, but we also use this to convert
@@ -89,7 +93,7 @@ impl fmt::Debug for CompletionItem {
let mut s = f.debug_struct("CompletionItem");
s.field("label", &self.label).field("source_range", &self.source_range);
if self.text_edit.len() == 1 {
- let atom = &self.text_edit.iter().next().unwrap();
+ let atom = self.text_edit.iter().next().unwrap();
s.field("delete", &atom.delete);
s.field("insert", &atom.insert);
} else {
@@ -425,13 +429,14 @@ impl Builder {
pub(crate) fn build(self, db: &RootDatabase) -> CompletionItem {
let _p = profile::span("item::Builder::build");
- let mut label = self.label;
+ let label = self.label;
+ let mut label_detail = None;
let mut lookup = self.lookup.unwrap_or_else(|| label.clone());
let insert_text = self.insert_text.unwrap_or_else(|| label.to_string());
if !self.doc_aliases.is_empty() {
let doc_aliases = self.doc_aliases.iter().join(", ");
- label = SmolStr::from(format!("{label} (alias {doc_aliases})"));
+ label_detail.replace(SmolStr::from(format!(" (alias {doc_aliases})")));
let lookup_doc_aliases = self
.doc_aliases
.iter()
@@ -453,11 +458,16 @@ impl Builder {
}
if let [import_edit] = &*self.imports_to_add {
// snippets can have multiple imports, but normal completions only have up to one
- if let Some(original_path) = import_edit.original_path.as_ref() {
- label = SmolStr::from(format!("{label} (use {})", original_path.display(db)));
- }
+ label_detail.replace(SmolStr::from(format!(
+ "{} (use {})",
+ label_detail.as_deref().unwrap_or_default(),
+ import_edit.import_path.display(db)
+ )));
} else if let Some(trait_name) = self.trait_name {
- label = SmolStr::from(format!("{label} (as {trait_name})"));
+ label_detail.replace(SmolStr::from(format!(
+ "{} (as {trait_name})",
+ label_detail.as_deref().unwrap_or_default(),
+ )));
}
let text_edit = match self.text_edit {
@@ -479,6 +489,7 @@ impl Builder {
CompletionItem {
source_range: self.source_range,
label,
+ label_detail,
text_edit,
is_snippet: self.is_snippet,
detail: self.detail,
@@ -557,6 +568,13 @@ impl Builder {
self.relevance = relevance;
self
}
+ pub(crate) fn with_relevance(
+ &mut self,
+ relevance: impl FnOnce(CompletionRelevance) -> CompletionRelevance,
+ ) -> &mut Builder {
+ self.relevance = relevance(mem::take(&mut self.relevance));
+ self
+ }
pub(crate) fn trigger_call_info(&mut self) -> &mut Builder {
self.trigger_call_info = true;
self
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
index 2eaa42040..37a2828e8 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
@@ -1,6 +1,6 @@
//! `completions` crate provides utilities for generating completions of user input.
-#![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)]
+#![warn(rust_2018_idioms, unused_lifetimes)]
mod completions;
mod config;
@@ -169,6 +169,28 @@ pub fn completions(
return Some(completions.into());
}
+ // when the user types a bare `_` (that is it does not belong to an identifier)
+ // the user might just wanted to type a `_` for type inference or pattern discarding
+ // so try to suppress completions in those cases
+ if trigger_character == Some('_') && ctx.original_token.kind() == syntax::SyntaxKind::UNDERSCORE
+ {
+ if let CompletionAnalysis::NameRef(NameRefContext {
+ kind:
+ NameRefKind::Path(
+ path_ctx @ PathCompletionCtx {
+ kind: PathKind::Type { .. } | PathKind::Pat { .. },
+ ..
+ },
+ ),
+ ..
+ }) = analysis
+ {
+ if path_ctx.is_trivial_path() {
+ return None;
+ }
+ }
+ }
+
{
let acc = &mut completions;
@@ -241,6 +263,7 @@ pub fn resolve_completion_edits(
candidate,
config.insert_use.prefix_kind,
config.prefer_no_std,
+ config.prefer_prelude,
)
})
.find(|mod_path| mod_path.display(db).to_string() == full_import_path);
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
index dfe8fe7e2..2ea3f74d1 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
@@ -10,7 +10,7 @@ pub(crate) mod variant;
pub(crate) mod union_literal;
pub(crate) mod literal;
-use hir::{AsAssocItem, HasAttrs, HirDisplay, ScopeDef};
+use hir::{AsAssocItem, HasAttrs, HirDisplay, ModuleDef, ScopeDef, Type};
use ide_db::{
documentation::{Documentation, HasDocs},
helpers::item_name,
@@ -18,9 +18,10 @@ use ide_db::{
RootDatabase, SnippetCap, SymbolKind,
};
use syntax::{AstNode, SmolStr, SyntaxKind, TextRange};
+use text_edit::TextEdit;
use crate::{
- context::{DotAccess, PathCompletionCtx, PathKind, PatternContext},
+ context::{DotAccess, DotAccessKind, PathCompletionCtx, PathKind, PatternContext},
item::{Builder, CompletionRelevanceTypeMatch},
render::{
function::render_fn,
@@ -147,7 +148,42 @@ pub(crate) fn render_field(
.set_documentation(field.docs(db))
.set_deprecated(is_deprecated)
.lookup_by(name);
- item.insert_text(field_with_receiver(db, receiver.as_ref(), &escaped_name));
+
+ let is_field_access = matches!(dot_access.kind, DotAccessKind::Field { .. });
+ if !is_field_access || ty.is_fn() || ty.is_closure() {
+ let mut builder = TextEdit::builder();
+ // Using TextEdit, insert '(' before the struct name and ')' before the
+ // dot access, then comes the field name and optionally insert function
+ // call parens.
+
+ builder.replace(
+ ctx.source_range(),
+ field_with_receiver(db, receiver.as_ref(), &escaped_name).into(),
+ );
+
+ let expected_fn_type =
+ ctx.completion.expected_type.as_ref().is_some_and(|ty| ty.is_fn() || ty.is_closure());
+
+ if !expected_fn_type {
+ if let Some(receiver) = &dot_access.receiver {
+ if let Some(receiver) = ctx.completion.sema.original_ast_node(receiver.clone()) {
+ builder.insert(receiver.syntax().text_range().start(), "(".to_string());
+ builder.insert(ctx.source_range().end(), ")".to_string());
+
+ let is_parens_needed =
+ !matches!(dot_access.kind, DotAccessKind::Method { has_parens: true });
+
+ if is_parens_needed {
+ builder.insert(ctx.source_range().end(), "()".to_string());
+ }
+ }
+ }
+ }
+
+ item.text_edit(builder.finish());
+ } else {
+ item.insert_text(field_with_receiver(db, receiver.as_ref(), &escaped_name));
+ }
if let Some(receiver) = &dot_access.receiver {
if let Some(original) = ctx.completion.sema.original_ast_node(receiver.clone()) {
if let Some(ref_match) = compute_ref_match(ctx.completion, ty) {
@@ -304,6 +340,7 @@ fn render_resolution_path(
let cap = ctx.snippet_cap();
let db = completion.db;
let config = completion.config;
+ let requires_import = import_to_add.is_some();
let name = local_name.to_smol_str();
let mut item = render_resolution_simple_(ctx, &local_name, import_to_add, resolution);
@@ -334,8 +371,8 @@ fn render_resolution_path(
}
}
}
- if let ScopeDef::Local(local) = resolution {
- let ty = local.ty(db);
+
+ let mut set_item_relevance = |ty: Type| {
if !ty.is_unknown() {
item.detail(ty.display(db).to_string());
}
@@ -343,12 +380,38 @@ fn render_resolution_path(
item.set_relevance(CompletionRelevance {
type_match: compute_type_match(completion, &ty),
exact_name_match: compute_exact_name_match(completion, &name),
- is_local: true,
+ is_local: matches!(resolution, ScopeDef::Local(_)),
+ requires_import,
..CompletionRelevance::default()
});
path_ref_match(completion, path_ctx, &ty, &mut item);
};
+
+ match resolution {
+ ScopeDef::Local(local) => set_item_relevance(local.ty(db)),
+ ScopeDef::ModuleDef(ModuleDef::Adt(adt)) | ScopeDef::AdtSelfType(adt) => {
+ set_item_relevance(adt.ty(db))
+ }
+ // Filtered out above
+ ScopeDef::ModuleDef(
+ ModuleDef::Function(_) | ModuleDef::Variant(_) | ModuleDef::Macro(_),
+ ) => (),
+ ScopeDef::ModuleDef(ModuleDef::Const(konst)) => set_item_relevance(konst.ty(db)),
+ ScopeDef::ModuleDef(ModuleDef::Static(stat)) => set_item_relevance(stat.ty(db)),
+ ScopeDef::ModuleDef(ModuleDef::BuiltinType(bt)) => set_item_relevance(bt.ty(db)),
+ ScopeDef::ImplSelfType(imp) => set_item_relevance(imp.self_ty(db)),
+ ScopeDef::GenericParam(_)
+ | ScopeDef::Label(_)
+ | ScopeDef::Unknown
+ | ScopeDef::ModuleDef(
+ ModuleDef::Trait(_)
+ | ModuleDef::TraitAlias(_)
+ | ModuleDef::Module(_)
+ | ModuleDef::TypeAlias(_),
+ ) => (),
+ };
+
item
}
@@ -435,6 +498,21 @@ fn scope_def_is_deprecated(ctx: &RenderContext<'_>, resolution: ScopeDef) -> boo
}
}
+// FIXME: This checks types without possible coercions which some completions might want to do
+fn match_types(
+ ctx: &CompletionContext<'_>,
+ ty1: &hir::Type,
+ ty2: &hir::Type,
+) -> Option<CompletionRelevanceTypeMatch> {
+ if ty1 == ty2 {
+ Some(CompletionRelevanceTypeMatch::Exact)
+ } else if ty1.could_unify_with(ctx.db, ty2) {
+ Some(CompletionRelevanceTypeMatch::CouldUnify)
+ } else {
+ None
+ }
+}
+
fn compute_type_match(
ctx: &CompletionContext<'_>,
completion_ty: &hir::Type,
@@ -447,13 +525,7 @@ fn compute_type_match(
return None;
}
- if completion_ty == expected_type {
- Some(CompletionRelevanceTypeMatch::Exact)
- } else if expected_type.could_unify_with(ctx.db, completion_ty) {
- Some(CompletionRelevanceTypeMatch::CouldUnify)
- } else {
- None
- }
+ match_types(ctx, expected_type, completion_ty)
}
fn compute_exact_name_match(ctx: &CompletionContext<'_>, completion_name: &str) -> bool {
@@ -557,7 +629,11 @@ mod tests {
let tag = it.kind.tag();
let relevance = display_relevance(it.relevance);
- items.push(format!("{tag} {} {relevance}\n", it.label));
+ items.push(format!(
+ "{tag} {}{} {relevance}\n",
+ it.label,
+ it.label_detail.clone().unwrap_or_default(),
+ ));
if let Some((label, _indel, relevance)) = it.ref_match() {
let relevance = display_relevance(relevance);
@@ -596,6 +672,330 @@ mod tests {
}
#[test]
+ fn set_struct_type_completion_info() {
+ check_relevance(
+ r#"
+//- /lib.rs crate:dep
+
+pub mod test_mod_b {
+ pub struct Struct {}
+}
+
+pub mod test_mod_a {
+ pub struct Struct {}
+}
+
+//- /main.rs crate:main deps:dep
+
+fn test(input: dep::test_mod_b::Struct) { }
+
+fn main() {
+ test(Struct$0);
+}
+"#,
+ expect![[r#"
+ st dep::test_mod_b::Struct {…} [type_could_unify]
+ st Struct (use dep::test_mod_b::Struct) [type_could_unify+requires_import]
+ fn main() []
+ fn test(…) []
+ md dep []
+ st Struct (use dep::test_mod_a::Struct) [requires_import]
+ "#]],
+ );
+ }
+
+ #[test]
+ fn set_union_type_completion_info() {
+ check_relevance(
+ r#"
+//- /lib.rs crate:dep
+
+pub mod test_mod_b {
+ pub union Union {
+ a: i32,
+ b: i32
+ }
+}
+
+pub mod test_mod_a {
+ pub enum Union {
+ a: i32,
+ b: i32
+ }
+}
+
+//- /main.rs crate:main deps:dep
+
+fn test(input: dep::test_mod_b::Union) { }
+
+fn main() {
+ test(Union$0);
+}
+"#,
+ expect![[r#"
+ un Union (use dep::test_mod_b::Union) [type_could_unify+requires_import]
+ fn main() []
+ fn test(…) []
+ md dep []
+ en Union (use dep::test_mod_a::Union) [requires_import]
+ "#]],
+ );
+ }
+
+ #[test]
+ fn set_enum_type_completion_info() {
+ check_relevance(
+ r#"
+//- /lib.rs crate:dep
+
+pub mod test_mod_b {
+ pub enum Enum {
+ variant
+ }
+}
+
+pub mod test_mod_a {
+ pub enum Enum {
+ variant
+ }
+}
+
+//- /main.rs crate:main deps:dep
+
+fn test(input: dep::test_mod_b::Enum) { }
+
+fn main() {
+ test(Enum$0);
+}
+"#,
+ expect![[r#"
+ ev dep::test_mod_b::Enum::variant [type_could_unify]
+ en Enum (use dep::test_mod_b::Enum) [type_could_unify+requires_import]
+ fn main() []
+ fn test(…) []
+ md dep []
+ en Enum (use dep::test_mod_a::Enum) [requires_import]
+ "#]],
+ );
+ }
+
+ #[test]
+ fn set_enum_variant_type_completion_info() {
+ check_relevance(
+ r#"
+//- /lib.rs crate:dep
+
+pub mod test_mod_b {
+ pub enum Enum {
+ Variant
+ }
+}
+
+pub mod test_mod_a {
+ pub enum Enum {
+ Variant
+ }
+}
+
+//- /main.rs crate:main deps:dep
+
+fn test(input: dep::test_mod_b::Enum) { }
+
+fn main() {
+ test(Variant$0);
+}
+"#,
+ expect![[r#"
+ ev dep::test_mod_b::Enum::Variant [type_could_unify]
+ fn main() []
+ fn test(…) []
+ md dep []
+ "#]],
+ );
+ }
+
+ #[test]
+ fn set_fn_type_completion_info() {
+ check_relevance(
+ r#"
+//- /lib.rs crate:dep
+
+pub mod test_mod_b {
+ pub fn function(j: isize) -> i32 {}
+}
+
+pub mod test_mod_a {
+ pub fn function(i: usize) -> i32 {}
+}
+
+//- /main.rs crate:main deps:dep
+
+fn test(input: fn(usize) -> i32) { }
+
+fn main() {
+ test(function$0);
+}
+"#,
+ expect![[r#"
+ fn main []
+ fn test []
+ md dep []
+ fn function (use dep::test_mod_a::function) [requires_import]
+ fn function (use dep::test_mod_b::function) [requires_import]
+ "#]],
+ );
+ }
+
+ #[test]
+ fn set_const_type_completion_info() {
+ check_relevance(
+ r#"
+//- /lib.rs crate:dep
+
+pub mod test_mod_b {
+ pub const CONST: i32 = 1;
+}
+
+pub mod test_mod_a {
+ pub const CONST: i64 = 2;
+}
+
+//- /main.rs crate:main deps:dep
+
+fn test(input: i32) { }
+
+fn main() {
+ test(CONST$0);
+}
+"#,
+ expect![[r#"
+ ct CONST (use dep::test_mod_b::CONST) [type_could_unify+requires_import]
+ fn main() []
+ fn test(…) []
+ md dep []
+ ct CONST (use dep::test_mod_a::CONST) [requires_import]
+ "#]],
+ );
+ }
+
+ #[test]
+ fn set_static_type_completion_info() {
+ check_relevance(
+ r#"
+//- /lib.rs crate:dep
+
+pub mod test_mod_b {
+ pub static STATIC: i32 = 5;
+}
+
+pub mod test_mod_a {
+ pub static STATIC: i64 = 5;
+}
+
+//- /main.rs crate:main deps:dep
+
+fn test(input: i32) { }
+
+fn main() {
+ test(STATIC$0);
+}
+"#,
+ expect![[r#"
+ sc STATIC (use dep::test_mod_b::STATIC) [type_could_unify+requires_import]
+ fn main() []
+ fn test(…) []
+ md dep []
+ sc STATIC (use dep::test_mod_a::STATIC) [requires_import]
+ "#]],
+ );
+ }
+
+ #[test]
+ fn set_self_type_completion_info_with_params() {
+ check_relevance(
+ r#"
+//- /lib.rs crate:dep
+pub struct Struct;
+
+impl Struct {
+ pub fn Function(&self, input: i32) -> bool {
+ false
+ }
+}
+
+
+//- /main.rs crate:main deps:dep
+
+use dep::Struct;
+
+
+fn test(input: fn(&dep::Struct, i32) -> bool) { }
+
+fn main() {
+ test(Struct::Function$0);
+}
+
+"#,
+ expect![[r#"
+ me Function []
+ "#]],
+ );
+ }
+
+ #[test]
+ fn set_self_type_completion_info() {
+ check_relevance(
+ r#"
+//- /main.rs crate:main
+
+struct Struct;
+
+impl Struct {
+fn test(&self) {
+ func(Self$0);
+ }
+}
+
+fn func(input: Struct) { }
+
+"#,
+ expect![[r#"
+ st Struct [type]
+ st Self [type]
+ sp Self [type]
+ st Struct [type]
+ lc self [local]
+ fn func(…) []
+ me self.test() []
+ "#]],
+ );
+ }
+
+ #[test]
+ fn set_builtin_type_completion_info() {
+ check_relevance(
+ r#"
+//- /main.rs crate:main
+
+fn test(input: bool) { }
+ pub Input: bool = false;
+
+fn main() {
+ let input = false;
+ let inputbad = 3;
+ test(inp$0);
+}
+"#,
+ expect![[r#"
+ lc input [type+name+local]
+ lc inputbad [local]
+ fn main() []
+ fn test(…) []
+ "#]],
+ );
+ }
+
+ #[test]
fn enum_detail_includes_record_fields() {
check(
r#"
@@ -986,6 +1386,7 @@ use self::E::*;
kind: SymbolKind(
Enum,
),
+ detail: "E",
documentation: Documentation(
"enum docs",
),
@@ -1230,6 +1631,7 @@ fn go(world: &WorldSnapshot) { go(w$0) }
st WorldSnapshot {…} []
st &WorldSnapshot {…} [type]
st WorldSnapshot []
+ st &WorldSnapshot [type]
fn go(…) []
"#]],
);
@@ -1329,6 +1731,7 @@ fn main() {
st S []
st &mut S [type]
st S []
+ st &mut S [type]
fn foo(…) []
fn main() []
"#]],
@@ -1345,7 +1748,7 @@ fn main() {
expect![[r#"
lc s [type+name+local]
st S [type]
- st S []
+ st S [type]
fn foo(…) []
fn main() []
"#]],
@@ -1362,7 +1765,7 @@ fn main() {
expect![[r#"
lc ssss [type+local]
st S [type]
- st S []
+ st S [type]
fn foo(…) []
fn main() []
"#]],
@@ -1401,7 +1804,9 @@ fn main() {
st S []
st &S [type]
st S []
+ st &S [type]
st T []
+ st &T [type]
fn foo(…) []
fn main() []
md core []
@@ -1447,7 +1852,9 @@ fn main() {
st S []
st &mut S [type]
st S []
+ st &mut S [type]
st T []
+ st &mut T [type]
fn foo(…) []
fn main() []
md core []
@@ -1486,7 +1893,7 @@ fn bar(t: Foo) {}
expect![[r#"
ev Foo::A [type]
ev Foo::B [type]
- en Foo []
+ en Foo [type]
fn bar(…) []
fn foo() []
"#]],
@@ -1509,6 +1916,7 @@ fn bar(t: &Foo) {}
ev Foo::B []
ev &Foo::B [type]
en Foo []
+ en &Foo [type]
fn bar(…) []
fn foo() []
"#]],
@@ -1542,7 +1950,9 @@ fn main() {
st S []
st &S [type]
st S []
+ st &S [type]
st T []
+ st &T [type]
fn bar() []
fn &bar() [type]
fn foo(…) []
@@ -1596,7 +2006,7 @@ fn main() {
fn struct_field_method_ref() {
check_kinds(
r#"
-struct Foo { bar: u32 }
+struct Foo { bar: u32, qux: fn() }
impl Foo { fn baz(&self) -> u32 { 0 } }
fn foo(f: Foo) { let _: &u32 = f.b$0 }
@@ -1606,24 +2016,44 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 }
[
CompletionItem {
label: "baz()",
- source_range: 98..99,
- delete: 98..99,
+ source_range: 109..110,
+ delete: 109..110,
insert: "baz()$0",
kind: Method,
lookup: "baz",
detail: "fn(&self) -> u32",
- ref_match: "&@96",
+ ref_match: "&@107",
},
CompletionItem {
label: "bar",
- source_range: 98..99,
- delete: 98..99,
+ source_range: 109..110,
+ delete: 109..110,
insert: "bar",
kind: SymbolKind(
Field,
),
detail: "u32",
- ref_match: "&@96",
+ ref_match: "&@107",
+ },
+ CompletionItem {
+ label: "qux",
+ source_range: 109..110,
+ text_edit: TextEdit {
+ indels: [
+ Indel {
+ insert: "(",
+ delete: 107..107,
+ },
+ Indel {
+ insert: "qux)()",
+ delete: 109..110,
+ },
+ ],
+ },
+ kind: SymbolKind(
+ Field,
+ ),
+ detail: "fn()",
},
]
"#]],
@@ -1631,6 +2061,48 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 }
}
#[test]
+ fn expected_fn_type_ref() {
+ check_kinds(
+ r#"
+struct S { field: fn() }
+
+fn foo() {
+ let foo: fn() = S { fields: || {}}.fi$0;
+}
+"#,
+ &[CompletionItemKind::SymbolKind(SymbolKind::Field)],
+ expect![[r#"
+ [
+ CompletionItem {
+ label: "field",
+ source_range: 76..78,
+ delete: 76..78,
+ insert: "field",
+ kind: SymbolKind(
+ Field,
+ ),
+ detail: "fn()",
+ relevance: CompletionRelevance {
+ exact_name_match: false,
+ type_match: Some(
+ Exact,
+ ),
+ is_local: false,
+ is_item_from_trait: false,
+ is_name_already_imported: false,
+ requires_import: false,
+ is_op_method: false,
+ is_private_editable: false,
+ postfix_match: None,
+ is_definite: false,
+ },
+ },
+ ]
+ "#]],
+ )
+ }
+
+ #[test]
fn qualified_path_ref() {
check_kinds(
r#"
@@ -1689,8 +2161,8 @@ fn foo() {
lc foo [type+local]
ev Foo::A(…) [type_could_unify]
ev Foo::B [type_could_unify]
+ en Foo [type_could_unify]
fn foo() []
- en Foo []
fn bar() []
fn baz() []
"#]],
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs
index 8afce8db5..d23ed71fd 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs
@@ -62,6 +62,7 @@ fn render(
),
_ => (name.unescaped().to_smol_str(), name.to_smol_str()),
};
+
let mut item = CompletionItem::new(
if func.self_param(db).is_some() {
CompletionItemKind::Method
@@ -77,8 +78,31 @@ fn render(
.as_assoc_item(ctx.db())
.and_then(|trait_| trait_.containing_trait_or_trait_impl(ctx.db()))
.map_or(false, |trait_| completion.is_ops_trait(trait_));
+
+ let (has_dot_receiver, has_call_parens, cap) = match func_kind {
+ FuncKind::Function(&PathCompletionCtx {
+ kind: PathKind::Expr { .. },
+ has_call_parens,
+ ..
+ }) => (false, has_call_parens, ctx.completion.config.snippet_cap),
+ FuncKind::Method(&DotAccess { kind: DotAccessKind::Method { has_parens }, .. }, _) => {
+ (true, has_parens, ctx.completion.config.snippet_cap)
+ }
+ FuncKind::Method(DotAccess { kind: DotAccessKind::Field { .. }, .. }, _) => {
+ (true, false, ctx.completion.config.snippet_cap)
+ }
+ _ => (false, false, None),
+ };
+ let complete_call_parens = cap
+ .filter(|_| !has_call_parens)
+ .and_then(|cap| Some((cap, params(ctx.completion, func, &func_kind, has_dot_receiver)?)));
+
item.set_relevance(CompletionRelevance {
- type_match: compute_type_match(completion, &ret_type),
+ type_match: if has_call_parens || complete_call_parens.is_some() {
+ compute_type_match(completion, &ret_type)
+ } else {
+ compute_type_match(completion, &func.ty(db))
+ },
exact_name_match: compute_exact_name_match(completion, &call),
is_op_method,
..ctx.completion_relevance()
@@ -98,47 +122,19 @@ fn render(
_ => (),
}
+ let detail = if ctx.completion.config.full_function_signatures {
+ detail_full(db, func)
+ } else {
+ detail(db, func)
+ };
item.set_documentation(ctx.docs(func))
.set_deprecated(ctx.is_deprecated(func) || ctx.is_deprecated_assoc_item(func))
- .detail(detail(db, func))
+ .detail(detail)
.lookup_by(name.unescaped().to_smol_str());
- match ctx.completion.config.snippet_cap {
- Some(cap) => {
- let complete_params = match func_kind {
- FuncKind::Function(PathCompletionCtx {
- kind: PathKind::Expr { .. },
- has_call_parens: false,
- ..
- }) => Some(false),
- FuncKind::Method(
- DotAccess {
- kind:
- DotAccessKind::Method { has_parens: false } | DotAccessKind::Field { .. },
- ..
- },
- _,
- ) => Some(true),
- _ => None,
- };
- if let Some(has_dot_receiver) = complete_params {
- if let Some((self_param, params)) =
- params(ctx.completion, func, &func_kind, has_dot_receiver)
- {
- add_call_parens(
- &mut item,
- completion,
- cap,
- call,
- escaped_call,
- self_param,
- params,
- );
- }
- }
- }
- _ => (),
- };
+ if let Some((cap, (self_param, params))) = complete_call_parens {
+ add_call_parens(&mut item, completion, cap, call, escaped_call, self_param, params);
+ }
match ctx.import_to_add {
Some(import_to_add) => {
@@ -263,6 +259,21 @@ fn detail(db: &dyn HirDatabase, func: hir::Function) -> String {
detail
}
+fn detail_full(db: &dyn HirDatabase, func: hir::Function) -> String {
+ let signature = format!("{}", func.display(db));
+ let mut detail = String::with_capacity(signature.len());
+
+ for segment in signature.split_whitespace() {
+ if !detail.is_empty() {
+ detail.push(' ');
+ }
+
+ detail.push_str(segment);
+ }
+
+ detail
+}
+
fn params_display(db: &dyn HirDatabase, func: hir::Function) -> String {
if let Some(self_param) = func.self_param(db) {
let assoc_fn_params = func.assoc_fn_params(db);
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs b/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs
index 343719c53..e667e2e01 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs
@@ -179,8 +179,9 @@ fn import_edits(ctx: &CompletionContext<'_>, requires: &[GreenNode]) -> Option<V
item,
ctx.config.insert_use.prefix_kind,
ctx.config.prefer_no_std,
+ ctx.config.prefer_prelude,
)?;
- Some((path.len() > 1).then(|| LocatedImport::new(path.clone(), item, item, None)))
+ Some((path.len() > 1).then(|| LocatedImport::new(path.clone(), item, item)))
};
let mut res = Vec::with_capacity(requires.len());
for import in requires {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
index 2464e8d5f..f28afacc5 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
@@ -64,9 +64,11 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
enable_imports_on_the_fly: true,
enable_self_on_the_fly: true,
enable_private_editable: false,
+ full_function_signatures: false,
callable: Some(CallableSnippets::FillArguments),
snippet_cap: SnippetCap::new(true),
prefer_no_std: false,
+ prefer_prelude: true,
insert_use: InsertUseConfig {
granularity: ImportGranularity::Crate,
prefix_kind: PrefixKind::Plain,
@@ -148,16 +150,29 @@ fn render_completion_list(completions: Vec<CompletionItem>) -> String {
fn monospace_width(s: &str) -> usize {
s.chars().count()
}
- let label_width =
- completions.iter().map(|it| monospace_width(&it.label)).max().unwrap_or_default().min(22);
+ let label_width = completions
+ .iter()
+ .map(|it| {
+ monospace_width(&it.label)
+ + monospace_width(it.label_detail.as_deref().unwrap_or_default())
+ })
+ .max()
+ .unwrap_or_default()
+ .min(22);
completions
.into_iter()
.map(|it| {
let tag = it.kind.tag();
let var_name = format!("{tag} {}", it.label);
let mut buf = var_name;
+ if let Some(ref label_detail) = it.label_detail {
+ format_to!(buf, "{label_detail}");
+ }
if let Some(detail) = it.detail {
- let width = label_width.saturating_sub(monospace_width(&it.label));
+ let width = label_width.saturating_sub(
+ monospace_width(&it.label)
+ + monospace_width(&it.label_detail.unwrap_or_default()),
+ );
format_to!(buf, "{:width$} {}", "", detail, width = width);
}
if it.deprecated {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
index be5b7f8a3..b4f936b35 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
@@ -26,22 +26,22 @@ fn baz() {
"#,
// This should not contain `FooDesc {…}`.
expect![[r#"
- ct CONST
- en Enum
+ ct CONST Unit
+ en Enum Enum
fn baz() fn()
fn create_foo(…) fn(&FooDesc)
fn function() fn()
ma makro!(…) macro_rules! makro
md _69latrick
md module
- sc STATIC
- st FooDesc
- st Record
- st Tuple
- st Unit
- un Union
+ sc STATIC Unit
+ st FooDesc FooDesc
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
+ un Union Union
ev TupleV(…) TupleV(u32)
- bt u32
+ bt u32 u32
kw crate::
kw false
kw for
@@ -83,7 +83,7 @@ fn func(param0 @ (param1, param2): (i32, i32)) {
lc param0 (i32, i32)
lc param1 i32
lc param2 i32
- bt u32
+ bt u32 u32
kw crate::
kw false
kw for
@@ -117,24 +117,24 @@ impl Unit {
"#,
// `self` is in here twice, once as the module, once as the local
expect![[r#"
- ct CONST
+ ct CONST Unit
cp CONST_PARAM
- en Enum
+ en Enum Enum
fn function() fn()
fn local_func() fn()
lc self Unit
ma makro!(…) macro_rules! makro
md module
md qualified
- sp Self
- sc STATIC
- st Record
- st Tuple
- st Unit
+ sp Self Unit
+ sc STATIC Unit
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tp TypeParam
- un Union
+ un Union Union
ev TupleV(…) TupleV(u32)
- bt u32
+ bt u32 u32
kw const
kw crate::
kw enum
@@ -181,18 +181,18 @@ impl Unit {
}
"#,
expect![[r#"
- ct CONST
- en Enum
+ ct CONST Unit
+ en Enum Enum
fn function() fn()
ma makro!(…) macro_rules! makro
md module
md qualified
- sc STATIC
- st Record
- st Tuple
- st Unit
+ sc STATIC Unit
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt Trait
- un Union
+ un Union Union
ev TupleV(…) TupleV(u32)
?? Unresolved
"#]],
@@ -211,7 +211,7 @@ fn complete_in_block() {
"#,
expect![[r#"
fn foo() fn()
- bt u32
+ bt u32 u32
kw const
kw crate::
kw enum
@@ -256,7 +256,7 @@ fn complete_after_if_expr() {
"#,
expect![[r#"
fn foo() fn()
- bt u32
+ bt u32 u32
kw const
kw crate::
kw else
@@ -304,7 +304,7 @@ fn complete_in_match_arm() {
"#,
expect![[r#"
fn foo() fn()
- bt u32
+ bt u32 u32
kw crate::
kw false
kw for
@@ -328,7 +328,7 @@ fn completes_in_loop_ctx() {
r"fn my() { loop { $0 } }",
expect![[r#"
fn my() fn()
- bt u32
+ bt u32 u32
kw break
kw const
kw continue
@@ -370,7 +370,7 @@ fn completes_in_let_initializer() {
r#"fn main() { let _ = $0 }"#,
expect![[r#"
fn main() fn()
- bt u32
+ bt u32 u32
kw crate::
kw false
kw for
@@ -403,8 +403,8 @@ fn foo() {
"#,
expect![[r#"
fn foo() fn()
- st Foo
- bt u32
+ st Foo Foo
+ bt u32 u32
kw crate::
kw false
kw for
@@ -439,7 +439,7 @@ fn foo() {
expect![[r#"
fn foo() fn()
lc bar i32
- bt u32
+ bt u32 u32
kw crate::
kw false
kw for
@@ -470,7 +470,7 @@ fn quux(x: i32) {
fn quux(…) fn(i32)
lc x i32
ma m!(…) macro_rules! m
- bt u32
+ bt u32 u32
kw crate::
kw false
kw for
@@ -497,7 +497,7 @@ fn quux(x: i32) {
fn quux(…) fn(i32)
lc x i32
ma m!(…) macro_rules! m
- bt u32
+ bt u32 u32
kw crate::
kw false
kw for
@@ -683,11 +683,11 @@ fn brr() {
}
"#,
expect![[r#"
- en HH
+ en HH HH
fn brr() fn()
- st YoloVariant
+ st YoloVariant YoloVariant
st YoloVariant {…} YoloVariant { f: usize }
- bt u32
+ bt u32 u32
kw crate::
kw false
kw for
@@ -749,7 +749,7 @@ fn foo() { if foo {} $0 }
"#,
expect![[r#"
fn foo() fn()
- bt u32
+ bt u32 u32
kw const
kw crate::
kw else
@@ -789,7 +789,7 @@ fn foo() { if foo {} el$0 }
"#,
expect![[r#"
fn foo() fn()
- bt u32
+ bt u32 u32
kw const
kw crate::
kw else
@@ -829,7 +829,7 @@ fn foo() { bar(if foo {} $0) }
"#,
expect![[r#"
fn foo() fn()
- bt u32
+ bt u32 u32
kw crate::
kw else
kw else if
@@ -853,7 +853,7 @@ fn foo() { bar(if foo {} el$0) }
"#,
expect![[r#"
fn foo() fn()
- bt u32
+ bt u32 u32
kw crate::
kw else
kw else if
@@ -877,7 +877,7 @@ fn foo() { if foo {} $0 let x = 92; }
"#,
expect![[r#"
fn foo() fn()
- bt u32
+ bt u32 u32
kw const
kw crate::
kw else
@@ -917,7 +917,7 @@ fn foo() { if foo {} el$0 let x = 92; }
"#,
expect![[r#"
fn foo() fn()
- bt u32
+ bt u32 u32
kw const
kw crate::
kw else
@@ -957,7 +957,7 @@ fn foo() { if foo {} el$0 { let x = 92; } }
"#,
expect![[r#"
fn foo() fn()
- bt u32
+ bt u32 u32
kw const
kw crate::
kw else
@@ -1009,7 +1009,7 @@ pub struct UnstableThisShouldNotBeListed;
expect![[r#"
fn main() fn()
md std
- bt u32
+ bt u32 u32
kw const
kw crate::
kw enum
@@ -1060,8 +1060,8 @@ pub struct UnstableButWeAreOnNightlyAnyway;
expect![[r#"
fn main() fn()
md std
- st UnstableButWeAreOnNightlyAnyway
- bt u32
+ st UnstableButWeAreOnNightlyAnyway UnstableButWeAreOnNightlyAnyway
+ bt u32 u32
kw const
kw crate::
kw enum
@@ -1094,3 +1094,157 @@ pub struct UnstableButWeAreOnNightlyAnyway;
"#]],
);
}
+
+#[test]
+fn inside_format_args_completions_work() {
+ check_empty(
+ r#"
+//- minicore: fmt
+struct Foo;
+impl Foo {
+ fn foo(&self) {}
+}
+
+fn main() {
+ format_args!("{}", Foo.$0);
+}
+"#,
+ expect![[r#"
+ me foo() fn(&self)
+ sn box Box::new(expr)
+ sn call function(expr)
+ sn dbg dbg!(expr)
+ sn dbgr dbg!(&expr)
+ sn match match expr {}
+ sn ref &expr
+ sn refm &mut expr
+ sn unsafe unsafe {}
+ "#]],
+ );
+ check_empty(
+ r#"
+//- minicore: fmt
+struct Foo;
+impl Foo {
+ fn foo(&self) {}
+}
+
+fn main() {
+ format_args!("{}", Foo.f$0);
+}
+"#,
+ expect![[r#"
+ me foo() fn(&self)
+ sn box Box::new(expr)
+ sn call function(expr)
+ sn dbg dbg!(expr)
+ sn dbgr dbg!(&expr)
+ sn match match expr {}
+ sn ref &expr
+ sn refm &mut expr
+ sn unsafe unsafe {}
+ "#]],
+ );
+}
+
+#[test]
+fn inside_faulty_format_args_completions_work() {
+ check_empty(
+ r#"
+//- minicore: fmt
+struct Foo;
+impl Foo {
+ fn foo(&self) {}
+}
+
+fn main() {
+ format_args!("", Foo.$0);
+}
+"#,
+ expect![[r#"
+ me foo() fn(&self)
+ sn box Box::new(expr)
+ sn call function(expr)
+ sn dbg dbg!(expr)
+ sn dbgr dbg!(&expr)
+ sn match match expr {}
+ sn ref &expr
+ sn refm &mut expr
+ sn unsafe unsafe {}
+ "#]],
+ );
+ check_empty(
+ r#"
+//- minicore: fmt
+struct Foo;
+impl Foo {
+ fn foo(&self) {}
+}
+
+fn main() {
+ format_args!("", Foo.f$0);
+}
+"#,
+ expect![[r#"
+ me foo() fn(&self)
+ sn box Box::new(expr)
+ sn call function(expr)
+ sn dbg dbg!(expr)
+ sn dbgr dbg!(&expr)
+ sn match match expr {}
+ sn ref &expr
+ sn refm &mut expr
+ sn unsafe unsafe {}
+ "#]],
+ );
+ check_empty(
+ r#"
+//- minicore: fmt
+struct Foo;
+impl Foo {
+ fn foo(&self) {}
+}
+
+fn main() {
+ format_args!("{} {named} {captured} {named} {}", a, named = c, Foo.f$0);
+}
+"#,
+ expect![[r#"
+ me foo() fn(&self)
+ sn box Box::new(expr)
+ sn call function(expr)
+ sn dbg dbg!(expr)
+ sn dbgr dbg!(&expr)
+ sn match match expr {}
+ sn ref &expr
+ sn refm &mut expr
+ sn unsafe unsafe {}
+ "#]],
+ );
+ check_empty(
+ r#"
+//- minicore: fmt
+struct Foo;
+impl Foo {
+ fn foo(&self) {}
+}
+
+fn main() {
+ format_args!("{", Foo.f$0);
+}
+"#,
+ expect![[r#"
+ sn box Box::new(expr)
+ sn call function(expr)
+ sn dbg dbg!(expr)
+ sn dbgr dbg!(&expr)
+ sn if if expr {}
+ sn match match expr {}
+ sn not !expr
+ sn ref &expr
+ sn refm &mut expr
+ sn unsafe unsafe {}
+ sn while while expr {}
+ "#]],
+ );
+}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs
index 4cdfd546f..c58374f2e 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs
@@ -116,19 +116,47 @@ fn main() {
}
#[test]
-fn short_paths_are_ignored() {
- cov_mark::check!(flyimport_exact_on_short_path);
+fn short_paths_are_prefix_matched() {
+ cov_mark::check!(flyimport_prefix_on_short_path);
check(
r#"
//- /lib.rs crate:dep
-pub struct Bar;
+pub struct Barc;
pub struct Rcar;
pub struct Rc;
+pub const RC: () = ();
pub mod some_module {
pub struct Bar;
pub struct Rcar;
pub struct Rc;
+ pub const RC: () = ();
+}
+
+//- /main.rs crate:main deps:dep
+fn main() {
+ Rc$0
+}
+"#,
+ expect![[r#"
+ st Rc (use dep::Rc) Rc
+ st Rcar (use dep::Rcar) Rcar
+ st Rc (use dep::some_module::Rc) Rc
+ st Rcar (use dep::some_module::Rcar) Rcar
+ "#]],
+ );
+ check(
+ r#"
+//- /lib.rs crate:dep
+pub struct Barc;
+pub struct Rcar;
+pub struct Rc;
+pub const RC: () = ();
+pub mod some_module {
+ pub struct Bar;
+ pub struct Rcar;
+ pub struct Rc;
+ pub const RC: () = ();
}
//- /main.rs crate:main deps:dep
@@ -137,8 +165,36 @@ fn main() {
}
"#,
expect![[r#"
- st Rc (use dep::Rc)
- st Rc (use dep::some_module::Rc)
+ ct RC (use dep::RC) ()
+ st Rc (use dep::Rc) Rc
+ st Rcar (use dep::Rcar) Rcar
+ ct RC (use dep::some_module::RC) ()
+ st Rc (use dep::some_module::Rc) Rc
+ st Rcar (use dep::some_module::Rcar) Rcar
+ "#]],
+ );
+ check(
+ r#"
+//- /lib.rs crate:dep
+pub struct Barc;
+pub struct Rcar;
+pub struct Rc;
+pub const RC: () = ();
+pub mod some_module {
+ pub struct Bar;
+ pub struct Rcar;
+ pub struct Rc;
+ pub const RC: () = ();
+}
+
+//- /main.rs crate:main deps:dep
+fn main() {
+ RC$0
+}
+"#,
+ expect![[r#"
+ ct RC (use dep::RC) ()
+ ct RC (use dep::some_module::RC) ()
"#]],
);
}
@@ -171,10 +227,10 @@ fn main() {
}
"#,
expect![[r#"
- st ThirdStruct (use dep::some_module::ThirdStruct)
- st AfterThirdStruct (use dep::some_module::AfterThirdStruct)
- st ThiiiiiirdStruct (use dep::some_module::ThiiiiiirdStruct)
- "#]],
+ st ThirdStruct (use dep::some_module::ThirdStruct) ThirdStruct
+ st AfterThirdStruct (use dep::some_module::AfterThirdStruct) AfterThirdStruct
+ st ThiiiiiirdStruct (use dep::some_module::ThiiiiiirdStruct) ThiiiiiirdStruct
+ "#]],
);
}
@@ -253,7 +309,7 @@ fn trait_const_fuzzy_completion() {
check(
fixture,
expect![[r#"
- ct SPECIAL_CONST (use dep::test_mod::TestTrait)
+ ct SPECIAL_CONST (use dep::test_mod::TestTrait) u8
"#]],
);
@@ -541,8 +597,8 @@ fn main() {
}
"#,
expect![[r#"
- ct SPECIAL_CONST (use dep::test_mod::TestTrait) DEPRECATED
fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED
+ ct SPECIAL_CONST (use dep::test_mod::TestTrait) u8 DEPRECATED
"#]],
);
}
@@ -661,7 +717,7 @@ fn main() {
check(
fixture,
expect![[r#"
- st Item (use foo::bar::baz::Item)
+ st Item (use foo::bar) Item
"#]],
);
@@ -669,19 +725,19 @@ fn main() {
"Item",
fixture,
r#"
- use foo::bar;
+use foo::bar;
- mod foo {
- pub mod bar {
- pub mod baz {
- pub struct Item;
- }
- }
+mod foo {
+ pub mod bar {
+ pub mod baz {
+ pub struct Item;
}
+ }
+}
- fn main() {
- bar::baz::Item
- }"#,
+fn main() {
+ bar::baz::Item
+}"#,
);
}
@@ -703,7 +759,7 @@ fn main() {
check(
fixture,
expect![[r#"
- ct TEST_ASSOC (use foo::Item)
+ ct TEST_ASSOC (use foo::Item) usize
"#]],
);
@@ -747,8 +803,8 @@ fn main() {
check(
fixture,
expect![[r#"
- ct TEST_ASSOC (use foo::bar::Item)
- "#]],
+ ct TEST_ASSOC (use foo::bar) usize
+ "#]],
);
check_edit(
@@ -841,8 +897,8 @@ fn main() {
TES$0
}"#,
expect![[r#"
- ct TEST_CONST (use foo::TEST_CONST)
- "#]],
+ ct TEST_CONST (use foo::TEST_CONST) usize
+ "#]],
);
check(
@@ -858,9 +914,9 @@ fn main() {
tes$0
}"#,
expect![[r#"
- ct TEST_CONST (use foo::TEST_CONST)
- fn test_function() (use foo::test_function) fn() -> i32
- "#]],
+ ct TEST_CONST (use foo::TEST_CONST) usize
+ fn test_function() (use foo::test_function) fn() -> i32
+ "#]],
);
check(
@@ -873,9 +929,9 @@ mod foo {
}
fn main() {
- Te$0
+ Tes$0
}"#,
- expect![[]],
+ expect![""],
);
}
@@ -1082,8 +1138,8 @@ mod mud {
}
"#,
expect![[r#"
- st Struct (use crate::Struct)
- "#]],
+ st Struct (use crate::Struct) Struct
+ "#]],
);
}
@@ -1194,7 +1250,7 @@ enum Foo {
}
}"#,
expect![[r#"
- st Barbara (use foo::Barbara)
+ st Barbara (use foo::Barbara) Barbara
"#]],
)
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs
index 3ef2a7c94..de3fd0518 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs
@@ -18,15 +18,15 @@ fn target_type_or_trait_in_impl_block() {
impl Tra$0
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- st Record
- st Tuple
- st Unit
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt Trait
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
kw crate::
kw self::
"#]],
@@ -40,15 +40,15 @@ fn target_type_in_trait_impl_block() {
impl Trait for Str$0
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- st Record
- st Tuple
- st Unit
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt Trait
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
kw crate::
kw self::
"#]],
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs
index 8af6cce98..67cf551fc 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs
@@ -355,6 +355,35 @@ fn outer(Foo { bar$0 }: Foo) {}
}
#[test]
+fn completes_in_record_field_pat_with_generic_type_alias() {
+ check_empty(
+ r#"
+type Wrap<T> = T;
+
+enum X {
+ A { cool: u32, stuff: u32 },
+ B,
+}
+
+fn main() {
+ let wrapped = Wrap::<X>::A {
+ cool: 100,
+ stuff: 100,
+ };
+
+ if let Wrap::<X>::A { $0 } = &wrapped {};
+}
+"#,
+ expect![[r#"
+ fd cool u32
+ fd stuff u32
+ kw mut
+ kw ref
+ "#]],
+ )
+}
+
+#[test]
fn completes_in_fn_param() {
check_empty(
r#"
@@ -406,7 +435,7 @@ fn foo() {
}
"#,
expect![[r#"
- st Bar
+ st Bar Bar
kw crate::
kw self::
"#]],
@@ -421,7 +450,7 @@ fn foo() {
}
"#,
expect![[r#"
- st Foo
+ st Foo Foo
kw crate::
kw self::
"#]],
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/predicate.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/predicate.rs
index 789ad6634..46a3e97d3 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/predicate.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/predicate.rs
@@ -16,16 +16,16 @@ fn predicate_start() {
struct Foo<'lt, T, const C: usize> where $0 {}
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- st Foo<…>
- st Record
- st Tuple
- st Unit
+ st Foo<…> Foo<'_, {unknown}, _>
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt Trait
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
kw crate::
kw self::
"#]],
@@ -89,16 +89,16 @@ fn param_list_for_for_pred() {
struct Foo<'lt, T, const C: usize> where for<'a> $0 {}
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- st Foo<…>
- st Record
- st Tuple
- st Unit
+ st Foo<…> Foo<'_, {unknown}, _>
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt Trait
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
kw crate::
kw self::
"#]],
@@ -114,16 +114,16 @@ impl Record {
}
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- sp Self
- st Record
- st Tuple
- st Unit
+ sp Self Record
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt Trait
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
kw crate::
kw self::
"#]],
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/record.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/record.rs
index 65cefdb08..18afde1b7 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/record.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/record.rs
@@ -186,10 +186,10 @@ fn main() {
lc foo Foo
lc thing i32
md core
- st Foo
+ st Foo Foo
st Foo {…} Foo { foo1: u32, foo2: u32 }
tt Default
- bt u32
+ bt u32 u32
kw crate::
kw self::
"#]],
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs
index e80a28904..f96fb71f2 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs
@@ -2,10 +2,15 @@
use expect_test::{expect, Expect};
-use crate::tests::{
- check_edit, completion_list, completion_list_no_kw, completion_list_with_trigger_character,
+use crate::{
+ tests::{
+ check_edit, completion_list, completion_list_no_kw, completion_list_with_trigger_character,
+ },
+ CompletionItemKind,
};
+use super::{do_completion_with_config, TEST_CONFIG};
+
fn check_no_kw(ra_fixture: &str, expect: Expect) {
let actual = completion_list_no_kw(ra_fixture);
expect.assert_eq(&actual)
@@ -79,10 +84,10 @@ pub mod prelude {
}
"#,
expect![[r#"
- md std
- st Option
- bt u32
- "#]],
+ md std
+ st Option Option
+ bt u32 u32
+ "#]],
);
}
@@ -107,11 +112,11 @@ mod macros {
}
"#,
expect![[r#"
- fn f() fn()
- ma concat!(…) macro_rules! concat
- md std
- bt u32
- "#]],
+ fn f() fn()
+ ma concat!(…) macro_rules! concat
+ md std
+ bt u32 u32
+ "#]],
);
}
@@ -137,11 +142,11 @@ pub mod prelude {
}
"#,
expect![[r#"
- md core
- md std
- st String
- bt u32
- "#]],
+ md core
+ md std
+ st String String
+ bt u32 u32
+ "#]],
);
}
@@ -166,10 +171,10 @@ pub mod prelude {
}
"#,
expect![[r#"
- fn f() fn()
- md std
- bt u32
- "#]],
+ fn f() fn()
+ md std
+ bt u32 u32
+ "#]],
);
}
@@ -441,10 +446,10 @@ mod p {
}
"#,
expect![[r#"
- ct RIGHT_CONST
- fn right_fn() fn()
- st RightType
- "#]],
+ ct RIGHT_CONST u32
+ fn right_fn() fn()
+ st RightType WrongType
+ "#]],
);
check_edit(
@@ -876,7 +881,7 @@ fn main() {
fn main() fn()
lc foobar i32
ma x!(…) macro_rules! x
- bt u32
+ bt u32 u32
"#]],
)
}
@@ -1003,8 +1008,8 @@ fn here_we_go() {
"#,
expect![[r#"
fn here_we_go() fn()
- st Foo (alias Bar)
- bt u32
+ st Foo (alias Bar) Foo
+ bt u32 u32
kw const
kw crate::
kw enum
@@ -1052,8 +1057,8 @@ fn here_we_go() {
"#,
expect![[r#"
fn here_we_go() fn()
- st Foo (alias Bar, Qux, Baz)
- bt u32
+ st Foo (alias Bar, Qux, Baz) Foo
+ bt u32 u32
kw const
kw crate::
kw enum
@@ -1173,7 +1178,7 @@ fn bar() { qu$0 }
expect![[r#"
fn bar() fn()
fn foo() (alias qux) fn()
- bt u32
+ bt u32 u32
kw const
kw crate::
kw enum
@@ -1222,7 +1227,7 @@ fn here_we_go() {
}
"#,
expect![[r#"
- st Bar (alias Qux)
+ st Bar (alias Qux) Bar
"#]],
);
}
@@ -1241,7 +1246,7 @@ fn here_we_go() {
}
"#,
expect![[r#"
- st Bar (alias Qux)
+ st Bar (alias Qux) Bar
"#]],
);
}
@@ -1262,8 +1267,8 @@ fn here_we_go() {
expect![[r#"
fn here_we_go() fn()
md foo
- st Bar (alias Qux) (use foo::Bar)
- bt u32
+ st Bar (alias Qux) (use foo::Bar) Bar
+ bt u32 u32
kw crate::
kw false
kw for
@@ -1282,6 +1287,30 @@ fn here_we_go() {
}
#[test]
+fn completes_only_public() {
+ check(
+ r#"
+//- /e.rs
+pub(self) fn i_should_be_hidden() {}
+pub(in crate::e) fn i_should_also_be_hidden() {}
+pub fn i_am_public () {}
+
+//- /lib.rs crate:krate
+pub mod e;
+
+//- /main.rs deps:krate crate:main
+use krate::e;
+fn main() {
+ e::$0
+}"#,
+ expect![
+ "fn i_am_public() fn()
+"
+ ],
+ )
+}
+
+#[test]
fn completion_filtering_excludes_non_identifier_doc_aliases() {
check_edit(
"PartialOrdcmporder",
@@ -1303,3 +1332,176 @@ struct Foo<T: PartialOrd
"#,
);
}
+
+fn check_signatures(src: &str, kind: CompletionItemKind, reduced: Expect, full: Expect) {
+ const FULL_SIGNATURES_CONFIG: crate::CompletionConfig = {
+ let mut x = TEST_CONFIG;
+ x.full_function_signatures = true;
+ x
+ };
+
+ // reduced signature
+ let completion = do_completion_with_config(TEST_CONFIG, src, kind);
+ assert!(completion[0].detail.is_some());
+ reduced.assert_eq(completion[0].detail.as_ref().unwrap());
+
+ // full signature
+ let completion = do_completion_with_config(FULL_SIGNATURES_CONFIG, src, kind);
+ assert!(completion[0].detail.is_some());
+ full.assert_eq(completion[0].detail.as_ref().unwrap());
+}
+
+#[test]
+fn respects_full_function_signatures() {
+ check_signatures(
+ r#"
+pub fn foo<'x, T>(x: &'x mut T) -> u8 where T: Clone, { 0u8 }
+fn main() { fo$0 }
+"#,
+ CompletionItemKind::SymbolKind(ide_db::SymbolKind::Function),
+ expect!("fn(&mut T) -> u8"),
+ expect!("pub fn foo<'x, T>(x: &'x mut T) -> u8 where T: Clone,"),
+ );
+
+ check_signatures(
+ r#"
+struct Foo;
+struct Bar;
+impl Bar {
+ pub const fn baz(x: Foo) -> ! { loop {} };
+}
+
+fn main() { Bar::b$0 }
+"#,
+ CompletionItemKind::SymbolKind(ide_db::SymbolKind::Function),
+ expect!("const fn(Foo) -> !"),
+ expect!("pub const fn baz(x: Foo) -> !"),
+ );
+
+ check_signatures(
+ r#"
+struct Foo;
+struct Bar;
+impl Bar {
+ pub const fn baz<'foo>(&'foo mut self, x: &'foo Foo) -> ! { loop {} };
+}
+
+fn main() {
+ let mut bar = Bar;
+ bar.b$0
+}
+"#,
+ CompletionItemKind::Method,
+ expect!("const fn(&'foo mut self, &Foo) -> !"),
+ expect!("pub const fn baz<'foo>(&'foo mut self, x: &'foo Foo) -> !"),
+ );
+}
+
+#[test]
+fn skips_underscore() {
+ check_with_trigger_character(
+ r#"
+fn foo(_$0) { }
+"#,
+ Some('_'),
+ expect![[r#""#]],
+ );
+ check_with_trigger_character(
+ r#"
+fn foo(_: _$0) { }
+"#,
+ Some('_'),
+ expect![[r#""#]],
+ );
+ check_with_trigger_character(
+ r#"
+fn foo<T>() {
+ foo::<_$0>();
+}
+"#,
+ Some('_'),
+ expect![[r#""#]],
+ );
+ // underscore expressions are fine, they are invalid so the user definitely meant to type an
+ // underscored name here
+ check_with_trigger_character(
+ r#"
+fn foo() {
+ _$0
+}
+"#,
+ Some('_'),
+ expect![[r#"
+ fn foo() fn()
+ bt u32 u32
+ kw const
+ kw crate::
+ kw enum
+ kw extern
+ kw false
+ kw fn
+ kw for
+ kw if
+ kw if let
+ kw impl
+ kw let
+ kw loop
+ kw match
+ kw mod
+ kw return
+ kw self::
+ kw static
+ kw struct
+ kw trait
+ kw true
+ kw type
+ kw union
+ kw unsafe
+ kw use
+ kw while
+ kw while let
+ sn macro_rules
+ sn pd
+ sn ppd
+ "#]],
+ );
+}
+
+#[test]
+fn no_skip_underscore_ident() {
+ check_with_trigger_character(
+ r#"
+fn foo(a_$0) { }
+"#,
+ Some('_'),
+ expect![[r#"
+ kw mut
+ kw ref
+ "#]],
+ );
+ check_with_trigger_character(
+ r#"
+fn foo(_: a_$0) { }
+"#,
+ Some('_'),
+ expect![[r#"
+ bt u32 u32
+ kw crate::
+ kw self::
+ "#]],
+ );
+ check_with_trigger_character(
+ r#"
+fn foo<T>() {
+ foo::<a_$0>();
+}
+"#,
+ Some('_'),
+ expect![[r#"
+ tp T
+ bt u32 u32
+ kw crate::
+ kw self::
+ "#]],
+ );
+}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs
index d518dd764..c7161f82c 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs
@@ -17,18 +17,18 @@ struct Foo<'lt, T, const C: usize> {
}
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- sp Self
- st Foo<…>
- st Record
- st Tuple
- st Unit
+ sp Self Foo<'_, {unknown}, _>
+ st Foo<…> Foo<'_, {unknown}, _>
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt Trait
tp T
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
kw crate::
kw self::
"#]],
@@ -42,18 +42,18 @@ fn tuple_struct_field() {
struct Foo<'lt, T, const C: usize>(f$0);
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- sp Self
- st Foo<…>
- st Record
- st Tuple
- st Unit
+ sp Self Foo<'_, {unknown}, _>
+ st Foo<…> Foo<'_, {unknown}, _>
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt Trait
tp T
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
kw crate::
kw pub
kw pub(crate)
@@ -70,16 +70,16 @@ fn fn_return_type() {
fn x<'lt, T, const C: usize>() -> $0
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- st Record
- st Tuple
- st Unit
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt Trait
tp T
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
kw crate::
kw self::
"#]],
@@ -100,19 +100,19 @@ fn foo() -> B$0 {
}
"#,
expect![[r#"
- en Enum
- ma makro!(…) macro_rules! makro
- md module
- st Record
- st Tuple
- st Unit
- tt Trait
- un Union
- bt u32
- it ()
- kw crate::
- kw self::
- "#]],
+ en Enum Enum
+ ma makro!(…) macro_rules! makro
+ md module
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
+ tt Trait
+ un Union Union
+ bt u32 u32
+ it ()
+ kw crate::
+ kw self::
+ "#]],
)
}
@@ -124,16 +124,16 @@ struct Foo<T>(T);
const FOO: $0 = Foo(2);
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- st Foo<…>
- st Record
- st Tuple
- st Unit
+ st Foo<…> Foo<{unknown}>
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt Trait
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
it Foo<i32>
kw crate::
kw self::
@@ -151,15 +151,15 @@ fn f2() {
}
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- st Record
- st Tuple
- st Unit
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt Trait
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
it i32
kw crate::
kw self::
@@ -179,15 +179,15 @@ fn f2() {
}
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- st Record
- st Tuple
- st Unit
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt Trait
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
it u64
kw crate::
kw self::
@@ -204,15 +204,15 @@ fn f2(x: u64) -> $0 {
}
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- st Record
- st Tuple
- st Unit
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt Trait
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
it u64
kw crate::
kw self::
@@ -230,15 +230,15 @@ fn f2(x: $0) {
}
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- st Record
- st Tuple
- st Unit
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt Trait
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
it i32
kw crate::
kw self::
@@ -262,17 +262,17 @@ fn foo<'lt, T, const C: usize>() {
}
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md a
md module
- st Record
- st Tuple
- st Unit
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt Trait
tp T
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
it a::Foo<a::Foo<i32>>
kw crate::
kw self::
@@ -291,17 +291,17 @@ fn foo<'lt, T, const C: usize>() {
}
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- st Foo<…>
- st Record
- st Tuple
- st Unit
+ st Foo<…> Foo<{unknown}>
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt Trait
tp T
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
it Foo<i32>
kw crate::
kw self::
@@ -319,16 +319,16 @@ fn foo<'lt, T, const C: usize>() {
}
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- st Record
- st Tuple
- st Unit
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt Trait
tp T
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
kw crate::
kw self::
"#]],
@@ -341,14 +341,14 @@ fn foo<'lt, T, const C: usize>() {
}
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- st Record
- st Tuple
- st Unit
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt Trait
- un Union
+ un Union Union
"#]],
);
}
@@ -384,18 +384,18 @@ trait Trait2<T>: Trait1 {
fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {}
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- st Record
- st Tuple
- st Unit
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt Trait
tt Trait1
tt Trait2
tp T
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
kw crate::
kw self::
"#]],
@@ -409,15 +409,15 @@ trait Trait2<T> {
fn foo<'lt, T: Trait2<self::$0>, const CONST_PARAM: usize>(_: T) {}
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- st Record
- st Tuple
- st Unit
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt Trait
tt Trait2
- un Union
+ un Union Union
"#]],
);
}
@@ -434,18 +434,18 @@ trait Tr<T> {
impl Tr<$0
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- sp Self
- st Record
- st S
- st Tuple
- st Unit
+ sp Self dyn Tr<{unknown}>
+ st Record Record
+ st S S
+ st Tuple Tuple
+ st Unit Unit
tt Tr
tt Trait
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
kw crate::
kw self::
"#]],
@@ -481,16 +481,16 @@ trait MyTrait<T, U> {
fn f(t: impl MyTrait<u$0
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- st Record
- st Tuple
- st Unit
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt MyTrait
tt Trait
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
kw crate::
kw self::
"#]],
@@ -506,16 +506,16 @@ trait MyTrait<T, U> {
fn f(t: impl MyTrait<u8, u$0
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- st Record
- st Tuple
- st Unit
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt MyTrait
tt Trait
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
kw crate::
kw self::
"#]],
@@ -549,16 +549,16 @@ trait MyTrait<T, U = u8> {
fn f(t: impl MyTrait<u$0
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- st Record
- st Tuple
- st Unit
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt MyTrait
tt Trait
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
kw crate::
kw self::
"#]],
@@ -574,18 +574,18 @@ trait MyTrait<T, U = u8> {
fn f(t: impl MyTrait<u8, u$0
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- st Record
- st Tuple
- st Unit
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt MyTrait
tt Trait
ta Item1 = (as MyTrait) type Item1
ta Item2 = (as MyTrait) type Item2
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
kw crate::
kw self::
"#]],
@@ -619,16 +619,16 @@ trait MyTrait {
fn f(t: impl MyTrait<Item1 = $0
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- st Record
- st Tuple
- st Unit
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt MyTrait
tt Trait
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
kw crate::
kw self::
"#]],
@@ -644,16 +644,16 @@ trait MyTrait {
fn f(t: impl MyTrait<Item1 = u8, Item2 = $0
"#,
expect![[r#"
- en Enum
+ en Enum Enum
ma makro!(…) macro_rules! makro
md module
- st Record
- st Tuple
- st Unit
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
tt MyTrait
tt Trait
- un Union
- bt u32
+ un Union Union
+ bt u32 u32
kw crate::
kw self::
"#]],
@@ -668,7 +668,7 @@ trait MyTrait {
fn f(t: impl MyTrait<C = $0
"#,
expect![[r#"
- ct CONST
+ ct CONST Unit
ma makro!(…) macro_rules! makro
kw crate::
kw self::
@@ -691,9 +691,9 @@ pub struct S;
"#,
expect![[r#"
md std
- sp Self
- st Foo
- bt u32
+ sp Self Foo
+ st Foo Foo
+ bt u32 u32
kw crate::
kw self::
"#]],
@@ -716,10 +716,10 @@ pub struct S;
"#,
expect![[r#"
md std
- sp Self
- st Foo
- st S
- bt u32
+ sp Self Foo
+ st Foo Foo
+ st S S
+ bt u32 u32
kw crate::
kw self::
"#]],
@@ -739,19 +739,19 @@ fn completes_const_and_type_generics_separately() {
}
"#,
expect![[r#"
- en Enum
- ma makro!(…) macro_rules! makro
- md module
- st Foo
- st Record
- st Tuple
- st Unit
- tt Trait
- un Union
- bt u32
- kw crate::
- kw self::
- "#]],
+ en Enum Enum
+ ma makro!(…) macro_rules! makro
+ md module
+ st Foo Foo
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
+ tt Trait
+ un Union Union
+ bt u32 u32
+ kw crate::
+ kw self::
+ "#]],
);
// FIXME: This should probably also suggest completions for types, at least those that have
// associated constants usable in this position. For example, a user could be typing
@@ -766,12 +766,12 @@ fn completes_const_and_type_generics_separately() {
}
"#,
expect![[r#"
- ct CONST
- ct X
- ma makro!(…) macro_rules! makro
- kw crate::
- kw self::
- "#]],
+ ct CONST Unit
+ ct X usize
+ ma makro!(…) macro_rules! makro
+ kw crate::
+ kw self::
+ "#]],
);
// Method generic params
@@ -785,19 +785,19 @@ fn completes_const_and_type_generics_separately() {
}
"#,
expect![[r#"
- en Enum
- ma makro!(…) macro_rules! makro
- md module
- st Foo
- st Record
- st Tuple
- st Unit
- tt Trait
- un Union
- bt u32
- kw crate::
- kw self::
- "#]],
+ en Enum Enum
+ ma makro!(…) macro_rules! makro
+ md module
+ st Foo Foo
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
+ tt Trait
+ un Union Union
+ bt u32 u32
+ kw crate::
+ kw self::
+ "#]],
);
check(
r#"
@@ -809,12 +809,12 @@ fn completes_const_and_type_generics_separately() {
}
"#,
expect![[r#"
- ct CONST
- ct X
- ma makro!(…) macro_rules! makro
- kw crate::
- kw self::
- "#]],
+ ct CONST Unit
+ ct X usize
+ ma makro!(…) macro_rules! makro
+ kw crate::
+ kw self::
+ "#]],
);
// Associated type generic params
@@ -828,20 +828,20 @@ fn completes_const_and_type_generics_separately() {
fn foo(_: impl Bar<Baz<F$0, 0> = ()>) {}
"#,
expect![[r#"
- en Enum
- ma makro!(…) macro_rules! makro
- md module
- st Foo
- st Record
- st Tuple
- st Unit
- tt Bar
- tt Trait
- un Union
- bt u32
- kw crate::
- kw self::
- "#]],
+ en Enum Enum
+ ma makro!(…) macro_rules! makro
+ md module
+ st Foo Foo
+ st Record Record
+ st Tuple Tuple
+ st Unit Unit
+ tt Bar
+ tt Trait
+ un Union Union
+ bt u32 u32
+ kw crate::
+ kw self::
+ "#]],
);
check(
r#"
@@ -853,12 +853,12 @@ fn completes_const_and_type_generics_separately() {
fn foo<T: Bar<Baz<(), $0> = ()>>() {}
"#,
expect![[r#"
- ct CONST
- ct X
- ma makro!(…) macro_rules! makro
- kw crate::
- kw self::
- "#]],
+ ct CONST Unit
+ ct X usize
+ ma makro!(…) macro_rules! makro
+ kw crate::
+ kw self::
+ "#]],
);
// Type generic params
@@ -871,12 +871,12 @@ fn completes_const_and_type_generics_separately() {
}
"#,
expect![[r#"
- ct CONST
- ct X
- ma makro!(…) macro_rules! makro
- kw crate::
- kw self::
- "#]],
+ ct CONST Unit
+ ct X usize
+ ma makro!(…) macro_rules! makro
+ kw crate::
+ kw self::
+ "#]],
);
// Type alias generic params
@@ -890,12 +890,12 @@ fn completes_const_and_type_generics_separately() {
}
"#,
expect![[r#"
- ct CONST
- ct X
- ma makro!(…) macro_rules! makro
- kw crate::
- kw self::
- "#]],
+ ct CONST Unit
+ ct X usize
+ ma makro!(…) macro_rules! makro
+ kw crate::
+ kw self::
+ "#]],
);
// Enum variant params
@@ -908,12 +908,12 @@ fn completes_const_and_type_generics_separately() {
}
"#,
expect![[r#"
- ct CONST
- ct X
- ma makro!(…) macro_rules! makro
- kw crate::
- kw self::
- "#]],
+ ct CONST Unit
+ ct X usize
+ ma makro!(…) macro_rules! makro
+ kw crate::
+ kw self::
+ "#]],
);
// Trait params
@@ -924,12 +924,12 @@ fn completes_const_and_type_generics_separately() {
impl Foo<(), $0> for () {}
"#,
expect![[r#"
- ct CONST
- ct X
- ma makro!(…) macro_rules! makro
- kw crate::
- kw self::
- "#]],
+ ct CONST Unit
+ ct X usize
+ ma makro!(…) macro_rules! makro
+ kw crate::
+ kw self::
+ "#]],
);
// Trait alias params
@@ -942,12 +942,12 @@ fn completes_const_and_type_generics_separately() {
fn foo<T: Bar<X$0, ()>>() {}
"#,
expect![[r#"
- ct CONST
- ct X
- ma makro!(…) macro_rules! makro
- kw crate::
- kw self::
- "#]],
+ ct CONST Unit
+ ct X usize
+ ma makro!(…) macro_rules! makro
+ kw crate::
+ kw self::
+ "#]],
);
// Omitted lifetime params
@@ -957,7 +957,7 @@ struct S<'a, 'b, const C: usize, T>(core::marker::PhantomData<&'a &'b T>);
fn foo<'a>() { S::<F$0, _>; }
"#,
expect![[r#"
- ct CONST
+ ct CONST Unit
ma makro!(…) macro_rules! makro
kw crate::
kw self::
@@ -970,7 +970,7 @@ struct S<'a, 'b, const C: usize, T>(core::marker::PhantomData<&'a &'b T>);
fn foo<'a>() { S::<'static, 'static, F$0, _>; }
"#,
expect![[r#"
- ct CONST
+ ct CONST Unit
ma makro!(…) macro_rules! makro
kw crate::
kw self::
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/use_tree.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/use_tree.rs
index 4c74dba52..167bdec54 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/use_tree.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/use_tree.rs
@@ -65,7 +65,7 @@ use self::{foo::*, bar$0};
"#,
expect![[r#"
md foo
- st S
+ st S S
"#]],
);
}
@@ -82,7 +82,7 @@ mod foo {
use foo::{bar::$0}
"#,
expect![[r#"
- st FooBar
+ st FooBar FooBar
"#]],
);
check(
@@ -115,7 +115,7 @@ mod foo {
use foo::{bar::{baz::$0}}
"#,
expect![[r#"
- st FooBarBaz
+ st FooBarBaz FooBarBaz
"#]],
);
check(
@@ -152,7 +152,7 @@ struct Bar;
"#,
expect![[r#"
ma foo macro_rules! foo_
- st Foo
+ st Foo Foo
"#]],
);
}
@@ -193,7 +193,7 @@ struct Bar;
"#,
expect![[r#"
md foo
- st Bar
+ st Bar Bar
"#]],
);
}
@@ -212,7 +212,7 @@ struct Bar;
expect![[r#"
md bar
md foo
- st Bar
+ st Bar Bar
"#]],
);
}
@@ -230,7 +230,7 @@ mod a {
}
"#,
expect![[r#"
- ct A
+ ct A usize
md b
kw super::
"#]],
@@ -248,7 +248,7 @@ struct Bar;
"#,
expect![[r#"
md foo
- st Bar
+ st Bar Bar
"#]],
);
}
@@ -265,7 +265,7 @@ pub mod foo {}
"#,
expect![[r#"
md foo
- st Foo
+ st Foo Foo
"#]],
);
}
@@ -425,7 +425,7 @@ marco_rules! m { () => {} }
expect![[r#"
fn foo fn()
md simd
- st S
+ st S S
"#]],
);
}