From 9918693037dce8aa4bb6f08741b6812923486c18 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 19 Jun 2024 11:26:03 +0200 Subject: Merging upstream version 1.76.0+dfsg1. Signed-off-by: Daniel Baumann --- .../rust-analyzer/crates/ide-completion/Cargo.toml | 2 +- .../crates/ide-completion/src/completions.rs | 1 + .../crates/ide-completion/src/completions/dot.rs | 181 ++++++- .../crates/ide-completion/src/completions/expr.rs | 2 + .../ide-completion/src/completions/flyimport.rs | 33 +- .../src/completions/item_list/trait_impl.rs | 30 +- .../crates/ide-completion/src/completions/mod_.rs | 2 +- .../ide-completion/src/completions/record.rs | 25 + .../crates/ide-completion/src/completions/use_.rs | 4 +- .../crates/ide-completion/src/config.rs | 2 + .../crates/ide-completion/src/item.rs | 34 +- .../rust-analyzer/crates/ide-completion/src/lib.rs | 25 +- .../crates/ide-completion/src/render.rs | 522 ++++++++++++++++++++- .../crates/ide-completion/src/render/function.rs | 87 ++-- .../crates/ide-completion/src/snippet.rs | 3 +- .../crates/ide-completion/src/tests.rs | 21 +- .../crates/ide-completion/src/tests/expression.rs | 252 ++++++++-- .../crates/ide-completion/src/tests/flyimport.rs | 126 +++-- .../crates/ide-completion/src/tests/item.rs | 24 +- .../crates/ide-completion/src/tests/pattern.rs | 33 +- .../crates/ide-completion/src/tests/predicate.rs | 42 +- .../crates/ide-completion/src/tests/record.rs | 4 +- .../crates/ide-completion/src/tests/special.rs | 270 +++++++++-- .../crates/ide-completion/src/tests/type_pos.rs | 486 +++++++++---------- .../crates/ide-completion/src/tests/use_tree.rs | 20 +- 25 files changed, 1700 insertions(+), 531 deletions(-) (limited to 'src/tools/rust-analyzer/crates/ide-completion') 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) { "#]], ); } + + #[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 { + foo: F, +} + +impl Foo { + fn new(foo: F) -> Foo { + Foo { foo } + } +} + +impl> Foo { + 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 { + foo: F, +} + +impl Foo { + fn new(foo: F) -> Foo { + Foo { foo } + } +} + +impl> Foo { + 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 @@ -427,6 +427,31 @@ fn foo() { ..Default::default() }; } +"#, + ); + } + + #[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, pub snippet_cap: Option, pub insert_use: InsertUseConfig, pub prefer_no_std: bool, + pub prefer_prelude: bool, pub snippets: Vec, pub limit: Option, } 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, + /// 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 { + 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); @@ -595,6 +671,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( @@ -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,30 +2016,92 @@ 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()", }, ] "#]], ); } + #[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( @@ -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 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) -> 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 @@ -354,6 +354,35 @@ fn outer(Foo { bar$0 }: Foo) {} ) } +#[test] +fn completes_in_record_field_pat_with_generic_type_alias() { + check_empty( + r#" +type Wrap = T; + +enum X { + A { cool: u32, stuff: u32 }, + B, +} + +fn main() { + let wrapped = Wrap::::A { + cool: 100, + stuff: 100, + }; + + if let Wrap::::A { $0 } = &wrapped {}; +} +"#, + expect![[r#" + fd cool u32 + fd stuff u32 + kw mut + kw ref + "#]], + ) +} + #[test] fn completes_in_fn_param() { check_empty( @@ -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 @@ -1281,6 +1286,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( @@ -1303,3 +1332,176 @@ struct Foo(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() { + 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() { + foo::(); +} +"#, + 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); 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 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> 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 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: 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 { fn foo<'lt, T: Trait2, 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 { 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 { fn f(t: impl MyTrait { fn f(t: impl MyTrait { fn f(t: impl MyTrait { fn f(t: impl MyTrait = ()>) {} "#, 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 = ()>>() {} "#, 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>() {} "#, 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::; } "#, 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 "#]], ); } -- cgit v1.2.3