summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/ide-completion
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:58 +0000
commita4b7ed7a42c716ab9f05e351f003d589124fd55d (patch)
treeb620cd3f223850b28716e474e80c58059dca5dd4 /src/tools/rust-analyzer/crates/ide-completion
parentAdding upstream version 1.67.1+dfsg1. (diff)
downloadrustc-a4b7ed7a42c716ab9f05e351f003d589124fd55d.tar.xz
rustc-a4b7ed7a42c716ab9f05e351f003d589124fd55d.zip
Adding upstream version 1.68.2+dfsg1.upstream/1.68.2+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tools/rust-analyzer/crates/ide-completion')
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/lint.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs20
-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/fn_param.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs63
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs154
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix/format_like.rs27
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/record.rs67
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/snippet.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context.rs28
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs20
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/item.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/lib.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render.rs13
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/const_.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs12
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/type_alias.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/variant.rs23
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs24
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs92
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/predicate.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs90
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs2
39 files changed, 538 insertions, 170 deletions
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 296dfc142..eb87d6c58 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs
@@ -133,7 +133,7 @@ impl Completions {
if incomplete_let && snippet.ends_with('}') {
// complete block expression snippets with a trailing semicolon, if inside an incomplete let
cov_mark::hit!(let_semi);
- item.insert_snippet(cap, format!("{};", snippet));
+ item.insert_snippet(cap, format!("{snippet};"));
} else {
item.insert_snippet(cap, snippet);
}
@@ -494,7 +494,7 @@ impl Completions {
pattern_ctx,
path_ctx,
variant,
- local_name.clone(),
+ local_name,
None,
));
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs
index d9fe94cb4..bb950c76f 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs
@@ -357,7 +357,7 @@ fn parse_comma_sep_expr(input: ast::TokenTree) -> Option<Vec<ast::Expr>> {
Some(
input_expressions
.into_iter()
- .filter_map(|(is_sep, group)| (!is_sep).then(|| group))
+ .filter_map(|(is_sep, group)| (!is_sep).then_some(group))
.filter_map(|mut tokens| syntax::hacks::parse_expr_from_str(&tokens.join("")))
.collect::<Vec<ast::Expr>>(),
)
@@ -371,9 +371,7 @@ fn attributes_are_sorted() {
attrs.for_each(|next| {
assert!(
prev < next,
- r#"ATTRIBUTES array is not sorted, "{}" should come after "{}""#,
- prev,
- next
+ r#"ATTRIBUTES array is not sorted, "{prev}" should come after "{next}""#
);
prev = next;
});
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs
index 311060143..7ef4ff30b 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs
@@ -11,7 +11,7 @@ use crate::{completions::Completions, context::CompletionContext, CompletionItem
pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext<'_>) {
let add_completion = |item: &str| {
let mut completion = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), item);
- completion.insert_text(format!(r#""{}""#, item));
+ completion.insert_text(format!(r#""{item}""#));
acc.add(completion.build());
};
@@ -29,7 +29,7 @@ pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext<'_>) {
Some("target_vendor") => KNOWN_VENDOR.iter().copied().for_each(add_completion),
Some("target_endian") => ["little", "big"].into_iter().for_each(add_completion),
Some(name) => ctx.krate.potential_cfg(ctx.db).get_cfg_values(name).cloned().for_each(|s| {
- let insert_text = format!(r#""{}""#, s);
+ let insert_text = format!(r#""{s}""#);
let mut item = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s);
item.insert_text(insert_text);
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/lint.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/lint.rs
index 967f6ddd9..818c3cfd5 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/lint.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/lint.rs
@@ -51,7 +51,7 @@ pub(super) fn complete_lint(
continue;
}
let label = match qual {
- Some(qual) if !is_qualified => format!("{}::{}", qual, name),
+ Some(qual) if !is_qualified => format!("{qual}::{name}"),
_ => name.to_owned(),
};
let mut item = CompletionItem::new(SymbolKind::Attribute, ctx.source_range(), label);
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 02004ff7b..7c6e5e100 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
@@ -32,12 +32,12 @@ pub(crate) fn complete_dot(
complete_fields(
acc,
ctx,
- &receiver_ty,
+ 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),
);
}
- complete_methods(ctx, &receiver_ty, |func| acc.add_method(ctx, dot_access, func, None, None));
+ complete_methods(ctx, receiver_ty, |func| acc.add_method(ctx, dot_access, func, None, None));
}
pub(crate) fn complete_undotted_self(
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs
index 09e95e53d..1002be211 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs
@@ -68,28 +68,26 @@ mod tests {
&format!(
r#"
#[rustc_builtin_macro]
- macro_rules! {} {{
+ macro_rules! {macro_name} {{
($var:literal) => {{ 0 }}
}}
fn main() {{
- let foo = {}!("CAR$0");
+ let foo = {macro_name}!("CAR$0");
}}
- "#,
- macro_name, macro_name
+ "#
),
&format!(
r#"
#[rustc_builtin_macro]
- macro_rules! {} {{
+ macro_rules! {macro_name} {{
($var:literal) => {{ 0 }}
}}
fn main() {{
- let foo = {}!("CARGO_BIN_NAME");
+ let foo = {macro_name}!("CARGO_BIN_NAME");
}}
- "#,
- macro_name, macro_name
+ "#
),
);
}
@@ -112,7 +110,7 @@ mod tests {
"#;
let completions = completion_list(fixture);
- assert!(completions.is_empty(), "Completions weren't empty: {}", completions);
+ assert!(completions.is_empty(), "Completions weren't empty: {completions}");
}
#[test]
@@ -129,7 +127,7 @@ mod tests {
"#;
let completions = completion_list(fixture);
- assert!(completions.is_empty(), "Completions weren't empty: {}", completions);
+ assert!(completions.is_empty(), "Completions weren't empty: {completions}");
}
#[test]
@@ -145,6 +143,6 @@ mod tests {
"#;
let completions = completion_list(fixture);
- assert!(completions.is_empty(), "Completions weren't empty: {}", completions)
+ assert!(completions.is_empty(), "Completions weren't empty: {completions}")
}
}
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 3192b21cf..cfe4787f7 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
@@ -64,7 +64,7 @@ pub(crate) fn complete_expr_path(
acc.add_enum_variants(ctx, path_ctx, e);
}
- ctx.iterate_path_candidates(&ty, |item| {
+ ctx.iterate_path_candidates(ty, |item| {
add_assoc_item(acc, item);
});
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs
index f0ecc595a..d8b8a190e 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs
@@ -192,5 +192,5 @@ fn comma_wrapper(ctx: &CompletionContext<'_>) -> Option<(impl Fn(&str) -> String
matches!(prev_token_kind, SyntaxKind::COMMA | SyntaxKind::L_PAREN | SyntaxKind::PIPE);
let leading = if has_leading_comma { "" } else { ", " };
- Some((move |label: &_| (format!("{}{}{}", leading, label, trailing)), param.text_range()))
+ Some((move |label: &_| (format!("{leading}{label}{trailing}")), param.text_range()))
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs
index 038bdb427..5c46c5806 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs
@@ -13,7 +13,7 @@ pub(crate) fn format_string(
original: &ast::String,
expanded: &ast::String,
) {
- if !is_format_string(&expanded) {
+ if !is_format_string(expanded) {
return;
}
let cursor = ctx.position.offset;
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 7384a3f2d..9a060857e 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
@@ -37,7 +37,7 @@ use ide_db::{
traits::get_missing_assoc_items, SymbolKind,
};
use syntax::{
- ast::{self, edit_in_place::AttrsOwnerEdit},
+ ast::{self, edit_in_place::AttrsOwnerEdit, HasTypeBounds},
AstNode, SyntaxElement, SyntaxKind, TextRange, T,
};
use text_edit::TextEdit;
@@ -190,7 +190,7 @@ fn add_function_impl(
};
let mut item = CompletionItem::new(completion_kind, replacement_range, label);
- item.lookup_by(format!("fn {}", fn_name))
+ item.lookup_by(format!("fn {fn_name}"))
.set_documentation(func.docs(ctx.db))
.set_relevance(CompletionRelevance { is_item_from_trait: true, ..Default::default() });
@@ -205,11 +205,11 @@ fn add_function_impl(
let function_decl = function_declaration(&transformed_fn, source.file_id.is_macro());
match ctx.config.snippet_cap {
Some(cap) => {
- let snippet = format!("{} {{\n $0\n}}", function_decl);
+ let snippet = format!("{function_decl} {{\n $0\n}}");
item.snippet_edit(cap, TextEdit::replace(replacement_range, snippet));
}
None => {
- let header = format!("{} {{", function_decl);
+ let header = format!("{function_decl} {{");
item.text_edit(TextEdit::replace(replacement_range, header));
}
};
@@ -249,10 +249,10 @@ fn add_type_alias_impl(
) {
let alias_name = type_alias.name(ctx.db).unescaped().to_smol_str();
- let label = format!("type {} =", alias_name);
+ let label = format!("type {alias_name} =");
let mut item = CompletionItem::new(SymbolKind::TypeAlias, replacement_range, label);
- item.lookup_by(format!("type {}", alias_name))
+ item.lookup_by(format!("type {alias_name}"))
.set_documentation(type_alias.docs(ctx.db))
.set_relevance(CompletionRelevance { is_item_from_trait: true, ..Default::default() });
@@ -265,10 +265,21 @@ fn add_type_alias_impl(
};
let start = transformed_ty.syntax().text_range().start();
- let Some(end) = transformed_ty
- .eq_token()
- .map(|tok| tok.text_range().start())
- .or(transformed_ty.semicolon_token().map(|tok| tok.text_range().start())) else { return };
+
+ let end = if let Some(end) =
+ transformed_ty.colon_token().map(|tok| tok.text_range().start())
+ {
+ end
+ } else if let Some(end) = transformed_ty.eq_token().map(|tok| tok.text_range().start())
+ {
+ end
+ } else if let Some(end) =
+ transformed_ty.semicolon_token().map(|tok| tok.text_range().start())
+ {
+ end
+ } else {
+ return;
+ };
let len = end - start;
let mut decl = transformed_ty.syntax().text().slice(..len).to_string();
@@ -279,7 +290,7 @@ fn add_type_alias_impl(
match ctx.config.snippet_cap {
Some(cap) => {
- let snippet = format!("{}$0;", decl);
+ let snippet = format!("{decl}$0;");
item.snippet_edit(cap, TextEdit::replace(replacement_range, snippet));
}
None => {
@@ -310,10 +321,10 @@ fn add_const_impl(
};
let label = make_const_compl_syntax(&transformed_const, source.file_id.is_macro());
- let replacement = format!("{} ", label);
+ let replacement = format!("{label} ");
let mut item = CompletionItem::new(SymbolKind::Const, replacement_range, label);
- item.lookup_by(format!("const {}", const_name))
+ item.lookup_by(format!("const {const_name}"))
.set_documentation(const_.docs(ctx.db))
.set_relevance(CompletionRelevance {
is_item_from_trait: true,
@@ -322,7 +333,7 @@ fn add_const_impl(
match ctx.config.snippet_cap {
Some(cap) => item.snippet_edit(
cap,
- TextEdit::replace(replacement_range, format!("{}$0;", replacement)),
+ TextEdit::replace(replacement_range, format!("{replacement}$0;")),
),
None => item.text_edit(TextEdit::replace(replacement_range, replacement)),
};
@@ -834,11 +845,10 @@ trait Test {{
struct T;
impl Test for T {{
- {}
- {}
+ {hint}
+ {next_sibling}
}}
-"#,
- hint, next_sibling
+"#
),
&format!(
r#"
@@ -850,11 +860,10 @@ trait Test {{
struct T;
impl Test for T {{
- {}
- {}
+ {completed}
+ {next_sibling}
}}
-"#,
- completed, next_sibling
+"#
),
)
};
@@ -894,10 +903,9 @@ struct T;
impl Foo for T {{
// Comment
#[bar]
- {}
+ {hint}
}}
-"#,
- hint
+"#
),
&format!(
r#"
@@ -911,10 +919,9 @@ struct T;
impl Foo for T {{
// Comment
#[bar]
- {}
+ {completed}
}}
-"#,
- completed
+"#
),
)
};
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs
index b9bd47f7d..f4f37d77d 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs
@@ -5,7 +5,7 @@ mod format_like;
use hir::{Documentation, HasAttrs};
use ide_db::{imports::insert_use::ImportScope, ty_filter::TryEnum, SnippetCap};
use syntax::{
- ast::{self, AstNode, AstToken},
+ ast::{self, make, AstNode, AstToken},
SyntaxKind::{EXPR_STMT, STMT_LIST},
TextRange, TextSize,
};
@@ -61,7 +61,7 @@ pub(crate) fn complete_postfix(
let mut item = postfix_snippet(
"drop",
"fn drop(&mut self)",
- &format!("drop($0{})", receiver_text),
+ &format!("drop($0{receiver_text})"),
);
item.set_documentation(drop_fn.docs(ctx.db));
item.add_to(acc);
@@ -76,14 +76,14 @@ pub(crate) fn complete_postfix(
postfix_snippet(
"ifl",
"if let Ok {}",
- &format!("if let Ok($1) = {} {{\n $0\n}}", receiver_text),
+ &format!("if let Ok($1) = {receiver_text} {{\n $0\n}}"),
)
.add_to(acc);
postfix_snippet(
"while",
"while let Ok {}",
- &format!("while let Ok($1) = {} {{\n $0\n}}", receiver_text),
+ &format!("while let Ok($1) = {receiver_text} {{\n $0\n}}"),
)
.add_to(acc);
}
@@ -91,46 +91,44 @@ pub(crate) fn complete_postfix(
postfix_snippet(
"ifl",
"if let Some {}",
- &format!("if let Some($1) = {} {{\n $0\n}}", receiver_text),
+ &format!("if let Some($1) = {receiver_text} {{\n $0\n}}"),
)
.add_to(acc);
postfix_snippet(
"while",
"while let Some {}",
- &format!("while let Some($1) = {} {{\n $0\n}}", receiver_text),
+ &format!("while let Some($1) = {receiver_text} {{\n $0\n}}"),
)
.add_to(acc);
}
}
} else if receiver_ty.is_bool() || receiver_ty.is_unknown() {
- postfix_snippet("if", "if expr {}", &format!("if {} {{\n $0\n}}", receiver_text))
+ postfix_snippet("if", "if expr {}", &format!("if {receiver_text} {{\n $0\n}}"))
.add_to(acc);
- postfix_snippet(
- "while",
- "while expr {}",
- &format!("while {} {{\n $0\n}}", receiver_text),
- )
- .add_to(acc);
- postfix_snippet("not", "!expr", &format!("!{}", receiver_text)).add_to(acc);
+ postfix_snippet("while", "while expr {}", &format!("while {receiver_text} {{\n $0\n}}"))
+ .add_to(acc);
+ postfix_snippet("not", "!expr", &format!("!{receiver_text}")).add_to(acc);
} else if let Some(trait_) = ctx.famous_defs().core_iter_IntoIterator() {
if receiver_ty.impls_trait(ctx.db, trait_, &[]) {
postfix_snippet(
"for",
"for ele in expr {}",
- &format!("for ele in {} {{\n $0\n}}", receiver_text),
+ &format!("for ele in {receiver_text} {{\n $0\n}}"),
)
.add_to(acc);
}
}
- postfix_snippet("ref", "&expr", &format!("&{}", receiver_text)).add_to(acc);
- postfix_snippet("refm", "&mut expr", &format!("&mut {}", receiver_text)).add_to(acc);
+ postfix_snippet("ref", "&expr", &format!("&{receiver_text}")).add_to(acc);
+ postfix_snippet("refm", "&mut expr", &format!("&mut {receiver_text}")).add_to(acc);
// The rest of the postfix completions create an expression that moves an argument,
// so it's better to consider references now to avoid breaking the compilation
- let dot_receiver = include_references(dot_receiver);
- let receiver_text = get_receiver_text(&dot_receiver, receiver_is_ambiguous_float_literal);
+
+ let (dot_receiver, node_to_replace_with) = include_references(dot_receiver);
+ let receiver_text =
+ get_receiver_text(&node_to_replace_with, receiver_is_ambiguous_float_literal);
let postfix_snippet = match build_postfix_snippet_builder(ctx, cap, &dot_receiver) {
Some(it) => it,
None => return,
@@ -146,7 +144,7 @@ pub(crate) fn complete_postfix(
postfix_snippet(
"match",
"match expr {}",
- &format!("match {} {{\n Ok(${{1:_}}) => {{$2}},\n Err(${{3:_}}) => {{$0}},\n}}", receiver_text),
+ &format!("match {receiver_text} {{\n Ok(${{1:_}}) => {{$2}},\n Err(${{3:_}}) => {{$0}},\n}}"),
)
.add_to(acc);
}
@@ -155,8 +153,7 @@ pub(crate) fn complete_postfix(
"match",
"match expr {}",
&format!(
- "match {} {{\n Some(${{1:_}}) => {{$2}},\n None => {{$0}},\n}}",
- receiver_text
+ "match {receiver_text} {{\n Some(${{1:_}}) => {{$2}},\n None => {{$0}},\n}}"
),
)
.add_to(acc);
@@ -166,21 +163,21 @@ pub(crate) fn complete_postfix(
postfix_snippet(
"match",
"match expr {}",
- &format!("match {} {{\n ${{1:_}} => {{$0}},\n}}", receiver_text),
+ &format!("match {receiver_text} {{\n ${{1:_}} => {{$0}},\n}}"),
)
.add_to(acc);
}
}
- postfix_snippet("box", "Box::new(expr)", &format!("Box::new({})", receiver_text)).add_to(acc);
- postfix_snippet("dbg", "dbg!(expr)", &format!("dbg!({})", receiver_text)).add_to(acc); // fixme
- postfix_snippet("dbgr", "dbg!(&expr)", &format!("dbg!(&{})", receiver_text)).add_to(acc);
- postfix_snippet("call", "function(expr)", &format!("${{1}}({})", receiver_text)).add_to(acc);
+ postfix_snippet("box", "Box::new(expr)", &format!("Box::new({receiver_text})")).add_to(acc);
+ postfix_snippet("dbg", "dbg!(expr)", &format!("dbg!({receiver_text})")).add_to(acc); // fixme
+ postfix_snippet("dbgr", "dbg!(&expr)", &format!("dbg!(&{receiver_text})")).add_to(acc);
+ postfix_snippet("call", "function(expr)", &format!("${{1}}({receiver_text})")).add_to(acc);
if let Some(parent) = dot_receiver.syntax().parent().and_then(|p| p.parent()) {
if matches!(parent.kind(), STMT_LIST | EXPR_STMT) {
- postfix_snippet("let", "let", &format!("let $0 = {};", receiver_text)).add_to(acc);
- postfix_snippet("letm", "let mut", &format!("let mut $0 = {};", receiver_text))
+ postfix_snippet("let", "let", &format!("let $0 = {receiver_text};")).add_to(acc);
+ postfix_snippet("letm", "let mut", &format!("let mut $0 = {receiver_text};"))
.add_to(acc);
}
}
@@ -210,14 +207,35 @@ fn get_receiver_text(receiver: &ast::Expr, receiver_is_ambiguous_float_literal:
text.replace('\\', "\\\\").replace('$', "\\$")
}
-fn include_references(initial_element: &ast::Expr) -> ast::Expr {
+fn include_references(initial_element: &ast::Expr) -> (ast::Expr, ast::Expr) {
let mut resulting_element = initial_element.clone();
- while let Some(parent_ref_element) =
- resulting_element.syntax().parent().and_then(ast::RefExpr::cast)
+
+ while let Some(field_expr) = resulting_element.syntax().parent().and_then(ast::FieldExpr::cast)
{
- resulting_element = ast::Expr::from(parent_ref_element);
+ resulting_element = ast::Expr::from(field_expr);
}
- resulting_element
+
+ let mut new_element_opt = initial_element.clone();
+
+ if let Some(first_ref_expr) = resulting_element.syntax().parent().and_then(ast::RefExpr::cast) {
+ if let Some(expr) = first_ref_expr.expr() {
+ resulting_element = expr;
+ }
+
+ while let Some(parent_ref_element) =
+ resulting_element.syntax().parent().and_then(ast::RefExpr::cast)
+ {
+ resulting_element = ast::Expr::from(parent_ref_element);
+
+ new_element_opt = make::expr_ref(new_element_opt, false);
+ }
+ } else {
+ // If we do not find any ref expressions, restore
+ // all the progress of tree climbing
+ resulting_element = initial_element.clone();
+ }
+
+ (resulting_element, new_element_opt)
}
fn build_postfix_snippet_builder<'ctx>(
@@ -225,8 +243,7 @@ fn build_postfix_snippet_builder<'ctx>(
cap: SnippetCap,
receiver: &'ctx ast::Expr,
) -> Option<impl Fn(&str, &str, &str) -> Builder + 'ctx> {
- let receiver_syntax = receiver.syntax();
- let receiver_range = ctx.sema.original_range_opt(receiver_syntax)?.range;
+ let receiver_range = ctx.sema.original_range_opt(receiver.syntax())?.range;
if ctx.source_range().end() < receiver_range.start() {
// This shouldn't happen, yet it does. I assume this might be due to an incorrect token mapping.
return None;
@@ -278,7 +295,7 @@ fn add_custom_postfix_completions(
let body = snippet.postfix_snippet(receiver_text);
let mut builder =
postfix_snippet(trigger, snippet.description.as_deref().unwrap_or_default(), &body);
- builder.documentation(Documentation::new(format!("```rust\n{}\n```", body)));
+ builder.documentation(Documentation::new(format!("```rust\n{body}\n```")));
for import in imports.into_iter() {
builder.add_import(import);
}
@@ -549,7 +566,7 @@ fn main() { ControlFlow::Break('\\\\') }
);
check_edit_with_config(
- config.clone(),
+ config,
"break",
r#"
//- minicore: try
@@ -578,12 +595,12 @@ fn main() {
check_edit(
"format",
r#"fn main() { "{some_var:?}".$0 }"#,
- r#"fn main() { format!("{:?}", some_var) }"#,
+ r#"fn main() { format!("{some_var:?}") }"#,
);
check_edit(
"panic",
r#"fn main() { "Panic with {a}".$0 }"#,
- r#"fn main() { panic!("Panic with {}", a) }"#,
+ r#"fn main() { panic!("Panic with {a}") }"#,
);
check_edit(
"println",
@@ -616,22 +633,55 @@ fn main() {
#[test]
fn postfix_custom_snippets_completion_for_references() {
+ // https://github.com/rust-lang/rust-analyzer/issues/7929
+
+ let snippet = Snippet::new(
+ &[],
+ &["ok".into()],
+ &["Ok(${receiver})".into()],
+ "",
+ &[],
+ crate::SnippetScope::Expr,
+ )
+ .unwrap();
+
check_edit_with_config(
- CompletionConfig {
- snippets: vec![Snippet::new(
- &[],
- &["ok".into()],
- &["Ok(${receiver})".into()],
- "",
- &[],
- crate::SnippetScope::Expr,
- )
- .unwrap()],
- ..TEST_CONFIG
- },
+ CompletionConfig { snippets: vec![snippet.clone()], ..TEST_CONFIG },
+ "ok",
+ r#"fn main() { &&42.o$0 }"#,
+ r#"fn main() { Ok(&&42) }"#,
+ );
+
+ check_edit_with_config(
+ CompletionConfig { snippets: vec![snippet.clone()], ..TEST_CONFIG },
"ok",
r#"fn main() { &&42.$0 }"#,
r#"fn main() { Ok(&&42) }"#,
);
+
+ check_edit_with_config(
+ CompletionConfig { snippets: vec![snippet], ..TEST_CONFIG },
+ "ok",
+ r#"
+struct A {
+ a: i32,
+}
+
+fn main() {
+ let a = A {a :1};
+ &a.a.$0
+}
+ "#,
+ r#"
+struct A {
+ a: i32,
+}
+
+fn main() {
+ let a = A {a :1};
+ Ok(&a.a)
+}
+ "#,
+ );
}
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix/format_like.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix/format_like.rs
index b43bdb9ab..dfcc78e92 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix/format_like.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix/format_like.rs
@@ -54,7 +54,11 @@ pub(crate) fn add_format_like_completions(
if let Ok((out, exprs)) = parse_format_exprs(receiver_text.text()) {
let exprs = with_placeholders(exprs);
for (label, macro_name) in KINDS {
- let snippet = format!(r#"{}({}, {})"#, macro_name, out, exprs.join(", "));
+ let snippet = if exprs.is_empty() {
+ format!(r#"{}({})"#, macro_name, out)
+ } else {
+ format!(r#"{}({}, {})"#, macro_name, out, exprs.join(", "))
+ };
postfix_snippet(label, macro_name, &snippet).add_to(acc);
}
@@ -72,16 +76,29 @@ mod tests {
("eprintln!", "{}", r#"eprintln!("{}", $1)"#),
(
"log::info!",
- "{} {expr} {} {2 + 2}",
- r#"log::info!("{} {} {} {}", $1, expr, $2, 2 + 2)"#,
+ "{} {ident} {} {2 + 2}",
+ r#"log::info!("{} {ident} {} {}", $1, $2, 2 + 2)"#,
),
- ("format!", "{expr:?}", r#"format!("{:?}", expr)"#),
];
for (kind, input, output) in test_vector {
let (parsed_string, exprs) = parse_format_exprs(input).unwrap();
let exprs = with_placeholders(exprs);
- let snippet = format!(r#"{}("{}", {})"#, kind, parsed_string, exprs.join(", "));
+ let snippet = format!(r#"{kind}("{parsed_string}", {})"#, exprs.join(", "));
+ assert_eq!(&snippet, output);
+ }
+ }
+
+ #[test]
+ fn test_into_suggestion_no_epxrs() {
+ let test_vector = &[
+ ("println!", "{ident}", r#"println!("{ident}")"#),
+ ("format!", "{ident:?}", r#"format!("{ident:?}")"#),
+ ];
+
+ for (kind, input, output) in test_vector {
+ let (parsed_string, _exprs) = parse_format_exprs(input).unwrap();
+ let snippet = format!(r#"{}("{}")"#, kind, parsed_string);
assert_eq!(&snippet, output);
}
}
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 5d96fbd30..0521e735d 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
@@ -124,7 +124,12 @@ fn complete_fields(
#[cfg(test)]
mod tests {
- use crate::tests::check_edit;
+ use ide_db::SnippetCap;
+
+ use crate::{
+ tests::{check_edit, check_edit_with_config, TEST_CONFIG},
+ CompletionConfig,
+ };
#[test]
fn literal_struct_completion_edit() {
@@ -152,6 +157,66 @@ fn baz() {
}
#[test]
+ fn enum_variant_no_snippets() {
+ let conf = CompletionConfig { snippet_cap: SnippetCap::new(false), ..TEST_CONFIG };
+ // tuple variant
+ check_edit_with_config(
+ conf.clone(),
+ "Variant()",
+ r#"
+enum Enum {
+ Variant(usize),
+}
+
+impl Enum {
+ fn new(u: usize) -> Self {
+ Self::Va$0
+ }
+}
+"#,
+ r#"
+enum Enum {
+ Variant(usize),
+}
+
+impl Enum {
+ fn new(u: usize) -> Self {
+ Self::Variant
+ }
+}
+"#,
+ );
+
+ // record variant
+ check_edit_with_config(
+ conf,
+ "Variant{}",
+ r#"
+enum Enum {
+ Variant{u: usize},
+}
+
+impl Enum {
+ fn new(u: usize) -> Self {
+ Self::Va$0
+ }
+}
+"#,
+ r#"
+enum Enum {
+ Variant{u: usize},
+}
+
+impl Enum {
+ fn new(u: usize) -> Self {
+ Self::Variant
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
fn literal_struct_impl_self_completion() {
check_edit(
"Self{}",
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/snippet.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/snippet.rs
index 66adb4286..da1f0542d 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/snippet.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/snippet.rs
@@ -141,7 +141,7 @@ fn add_custom_completions(
};
let body = snip.snippet();
let mut builder = snippet(ctx, cap, trigger, &body);
- builder.documentation(Documentation::new(format!("```rust\n{}\n```", body)));
+ builder.documentation(Documentation::new(format!("```rust\n{body}\n```")));
for import in imports.into_iter() {
builder.add_import(import);
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs
index 8f9db2f94..37849c251 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs
@@ -58,7 +58,7 @@ pub(crate) fn complete_type_path(
trait_.items(ctx.sema.db).into_iter().for_each(|item| add_assoc_item(acc, item))
}
Qualified::TypeAnchor { ty: Some(ty), trait_: None } => {
- ctx.iterate_path_candidates(&ty, |item| {
+ ctx.iterate_path_candidates(ty, |item| {
add_assoc_item(acc, item);
});
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
index 9850813a0..aa77f4495 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
@@ -19,7 +19,7 @@ use syntax::{
ast::{self, AttrKind, NameOrNameRef},
AstNode,
SyntaxKind::{self, *},
- SyntaxToken, TextRange, TextSize,
+ SyntaxToken, TextRange, TextSize, T,
};
use text_edit::Indel;
@@ -569,6 +569,32 @@ impl<'a> CompletionContext<'a> {
// completing on
let original_token = original_file.syntax().token_at_offset(offset).left_biased()?;
+ // try to skip completions on path with invalid colons
+ // this approach works in normal path and inside token tree
+ match original_token.kind() {
+ T![:] => {
+ // return if no prev token before colon
+ let prev_token = original_token.prev_token()?;
+
+ // only has a single colon
+ if prev_token.kind() != T![:] {
+ return None;
+ }
+
+ // has 3 colon or 2 coloncolon in a row
+ // special casing this as per discussion in https://github.com/rust-lang/rust-analyzer/pull/13611#discussion_r1031845205
+ // and https://github.com/rust-lang/rust-analyzer/pull/13611#discussion_r1032812751
+ if prev_token
+ .prev_token()
+ .map(|t| t.kind() == T![:] || t.kind() == T![::])
+ .unwrap_or(false)
+ {
+ return None;
+ }
+ }
+ _ => {}
+ }
+
let AnalysisResult {
analysis,
expected: (expected_type, expected_name),
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
index c142a7305..e34824e22 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
@@ -226,7 +226,7 @@ fn analyze(
find_node_at_offset(&file_with_fake_ident, offset)
{
let parent = name_ref.syntax().parent()?;
- let (mut nameref_ctx, _) = classify_name_ref(&sema, &original_file, name_ref, parent)?;
+ let (mut nameref_ctx, _) = classify_name_ref(sema, &original_file, name_ref, parent)?;
if let NameRefKind::Path(path_ctx) = &mut nameref_ctx.kind {
path_ctx.kind = PathKind::Derive {
existing_derives: sema
@@ -277,7 +277,7 @@ fn analyze(
return Some((analysis, (None, None), QualifierCtx::default()));
}
};
- let expected = expected_type_and_name(sema, &self_token, &name_like);
+ let expected = expected_type_and_name(sema, self_token, &name_like);
let mut qual_ctx = QualifierCtx::default();
let analysis = match name_like {
ast::NameLike::Lifetime(lifetime) => {
@@ -286,7 +286,7 @@ fn analyze(
ast::NameLike::NameRef(name_ref) => {
let parent = name_ref.syntax().parent()?;
let (nameref_ctx, qualifier_ctx) =
- classify_name_ref(sema, &original_file, name_ref, parent.clone())?;
+ classify_name_ref(sema, &original_file, name_ref, parent)?;
qual_ctx = qualifier_ctx;
CompletionAnalysis::NameRef(nameref_ctx)
}
@@ -374,7 +374,7 @@ fn expected_type_and_name(
ast::ArgList(_) => {
cov_mark::hit!(expected_type_fn_param);
ActiveParameter::at_token(
- &sema,
+ sema,
token.clone(),
).map(|ap| {
let name = ap.ident().map(NameOrNameRef::Name);
@@ -507,7 +507,7 @@ fn classify_lifetime(
_ => LifetimeKind::Lifetime,
}
};
- let lifetime = find_node_at_offset(&original_file, lifetime.syntax().text_range().start());
+ let lifetime = find_node_at_offset(original_file, lifetime.syntax().text_range().start());
Some(LifetimeContext { lifetime, kind })
}
@@ -548,7 +548,7 @@ fn classify_name(
_ => return None,
}
};
- let name = find_node_at_offset(&original_file, name.syntax().text_range().start());
+ let name = find_node_at_offset(original_file, name.syntax().text_range().start());
Some(NameContext { name, kind })
}
@@ -558,7 +558,7 @@ fn classify_name_ref(
name_ref: ast::NameRef,
parent: SyntaxNode,
) -> Option<(NameRefContext, QualifierCtx)> {
- let nameref = find_node_at_offset(&original_file, name_ref.syntax().text_range().start());
+ let nameref = find_node_at_offset(original_file, name_ref.syntax().text_range().start());
let make_res = |kind| (NameRefContext { nameref: nameref.clone(), kind }, Default::default());
@@ -585,11 +585,7 @@ fn classify_name_ref(
original_file,
&record_field.parent_record_pat(),
),
- ..pattern_context_for(
- sema,
- original_file,
- record_field.parent_record_pat().clone().into(),
- )
+ ..pattern_context_for(sema, original_file, record_field.parent_record_pat().into())
});
return Some(make_res(kind));
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs
index 50845b388..a654a5db5 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs
@@ -19,7 +19,7 @@ fn check_expected_type_and_name(ra_fixture: &str, expect: Expect) {
let name =
completion_context.expected_name.map_or_else(|| "?".to_owned(), |name| name.to_string());
- expect.assert_eq(&format!("ty: {}, name: {}", ty, name));
+ expect.assert_eq(&format!("ty: {ty}, name: {name}"));
}
#[test]
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 27c3ccb35..657eab5b1 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
@@ -453,10 +453,10 @@ impl Builder {
// snippets can have multiple imports, but normal completions only have up to one
if let Some(original_path) = import_edit.original_path.as_ref() {
lookup = lookup.or_else(|| Some(label.clone()));
- label = SmolStr::from(format!("{} (use {})", label, original_path));
+ label = SmolStr::from(format!("{label} (use {original_path})"));
}
} else if let Some(trait_name) = self.trait_name {
- label = SmolStr::from(format!("{} (as {})", label, trait_name));
+ label = SmolStr::from(format!("{label} (as {trait_name})"));
}
let text_edit = match self.text_edit {
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 9d0044e55..4b48ec6bc 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
@@ -164,7 +164,6 @@ pub fn completions(
completions::vis::complete_vis_path(&mut completions, ctx, path_ctx, has_in_token);
}
}
- // prevent `(` from triggering unwanted completion noise
return Some(completions.into());
}
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 86302cb06..e48d1aecd 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
@@ -131,7 +131,7 @@ pub(crate) fn render_field(
item.detail(ty.display(ctx.db()).to_string())
.set_documentation(field.docs(ctx.db()))
.set_deprecated(is_deprecated)
- .lookup_by(name.clone());
+ .lookup_by(name);
item.insert_text(field_with_receiver(receiver.as_ref(), &escaped_name));
if let Some(receiver) = &dot_access.receiver {
if let Some(original) = ctx.completion.sema.original_ast_node(receiver.clone()) {
@@ -144,8 +144,7 @@ pub(crate) fn render_field(
}
fn field_with_receiver(receiver: Option<&hir::Name>, field_name: &str) -> SmolStr {
- receiver
- .map_or_else(|| field_name.into(), |receiver| format!("{}.{}", receiver, field_name).into())
+ receiver.map_or_else(|| field_name.into(), |receiver| format!("{receiver}.{field_name}").into())
}
pub(crate) fn render_tuple_field(
@@ -306,7 +305,7 @@ fn render_resolution_path(
item.lookup_by(name.clone())
.label(SmolStr::from_iter([&name, "<…>"]))
.trigger_call_info()
- .insert_snippet(cap, format!("{}<$0>", local_name));
+ .insert_snippet(cap, format!("{local_name}<$0>"));
}
}
}
@@ -528,13 +527,13 @@ mod tests {
let tag = it.kind().tag();
let relevance = display_relevance(it.relevance());
- items.push(format!("{} {} {}\n", tag, it.label(), relevance));
+ items.push(format!("{tag} {} {relevance}\n", it.label()));
if let Some((mutability, _offset, relevance)) = it.ref_match() {
let label = format!("&{}{}", mutability.as_keyword_for_ref(), it.label());
let relevance = display_relevance(relevance);
- items.push(format!("{} {} {}\n", tag, label, relevance));
+ items.push(format!("{tag} {label} {relevance}\n"));
}
items
@@ -563,7 +562,7 @@ mod tests {
.filter_map(|(cond, desc)| if cond { Some(desc) } else { None })
.join("+");
- format!("[{}]", relevance_factors)
+ format!("[{relevance_factors}]")
}
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/const_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/const_.rs
index 93ea825e0..70b19988c 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/const_.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/const_.rs
@@ -16,7 +16,7 @@ fn render(ctx: RenderContext<'_>, const_: hir::Const) -> Option<CompletionItem>
let (name, escaped_name) = (name.unescaped().to_smol_str(), name.to_smol_str());
let detail = const_.display(db).to_string();
- let mut item = CompletionItem::new(SymbolKind::Const, ctx.source_range(), name.clone());
+ let mut item = CompletionItem::new(SymbolKind::Const, ctx.source_range(), name);
item.set_documentation(ctx.docs(const_))
.set_deprecated(ctx.is_deprecated(const_) || ctx.is_deprecated_assoc_item(const_))
.detail(detail)
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 376120846..197592e78 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
@@ -53,7 +53,7 @@ fn render(
let (call, escaped_call) = match &func_kind {
FuncKind::Method(_, Some(receiver)) => (
format!("{}.{}", receiver.unescaped(), name.unescaped()).into(),
- format!("{}.{}", receiver, name).into(),
+ format!("{receiver}.{name}").into(),
),
_ => (name.unescaped().to_smol_str(), name.to_smol_str()),
};
@@ -162,7 +162,7 @@ pub(super) fn add_call_parens<'b>(
cov_mark::hit!(inserts_parens_for_function_calls);
let (snippet, label_suffix) = if self_param.is_none() && params.is_empty() {
- (format!("{}()$0", escaped_name), "()")
+ (format!("{escaped_name}()$0"), "()")
} else {
builder.trigger_call_info();
let snippet = if let Some(CallableSnippets::FillArguments) = ctx.config.callable {
@@ -174,7 +174,7 @@ pub(super) fn add_call_parens<'b>(
let smol_str = n.to_smol_str();
let text = smol_str.as_str().trim_start_matches('_');
let ref_ = ref_of_param(ctx, text, param.ty());
- f(&format_args!("${{{}:{}{}}}", index + offset, ref_, text))
+ f(&format_args!("${{{}:{ref_}{text}}}", index + offset))
}
None => {
let name = match param.ty().as_adt() {
@@ -185,7 +185,7 @@ pub(super) fn add_call_parens<'b>(
.map(|s| to_lower_snake_case(s.as_str()))
.unwrap_or_else(|| "_".to_string()),
};
- f(&format_args!("${{{}:{}}}", index + offset, name))
+ f(&format_args!("${{{}:{name}}}", index + offset))
}
}
});
@@ -200,12 +200,12 @@ pub(super) fn add_call_parens<'b>(
)
}
None => {
- format!("{}({})$0", escaped_name, function_params_snippet)
+ format!("{escaped_name}({function_params_snippet})$0")
}
}
} else {
cov_mark::hit!(suppress_arg_snippets);
- format!("{}($0)", escaped_name)
+ format!("{escaped_name}($0)")
};
(snippet, "(…)")
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs
index 0c791ac57..64dab02f7 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs
@@ -84,7 +84,7 @@ fn render(
}
_ => RenderedLiteral {
literal: escaped_qualified_name.clone(),
- detail: escaped_qualified_name.clone(),
+ detail: escaped_qualified_name,
},
};
@@ -96,7 +96,7 @@ fn render(
if !should_add_parens {
kind = StructKind::Unit;
}
- let label = format_literal_label(&qualified_name, kind);
+ let label = format_literal_label(&qualified_name, kind, snippet_cap);
let lookup = if qualified {
format_literal_lookup(&short_qualified_name.to_string(), kind)
} else {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs
index eabd0bd17..ffcad1185 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs
@@ -66,7 +66,7 @@ fn render(
match ctx.snippet_cap() {
Some(cap) if needs_bang && !has_call_parens => {
- let snippet = format!("{}!{}$0{}", escaped_name, bra, ket);
+ let snippet = format!("{escaped_name}!{bra}$0{ket}");
let lookup = banged_name(&name);
item.insert_snippet(cap, snippet).lookup_by(lookup);
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs
index c845ff21a..21b4bc217 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs
@@ -33,7 +33,7 @@ pub(crate) fn render_struct_pat(
let name = local_name.unwrap_or_else(|| strukt.name(ctx.db()));
let (name, escaped_name) = (name.unescaped().to_smol_str(), name.to_smol_str());
let kind = strukt.kind(ctx.db());
- let label = format_literal_label(name.as_str(), kind);
+ let label = format_literal_label(name.as_str(), kind, ctx.snippet_cap());
let lookup = format_literal_lookup(name.as_str(), kind);
let pat = render_pat(&ctx, pattern_ctx, &escaped_name, kind, &visible_fields, fields_omitted)?;
@@ -67,7 +67,7 @@ pub(crate) fn render_variant_pat(
}
_ => {
let kind = variant.kind(ctx.db());
- let label = format_literal_label(name.as_str(), kind);
+ let label = format_literal_label(name.as_str(), kind, ctx.snippet_cap());
let lookup = format_literal_lookup(name.as_str(), kind);
let pat = render_pat(
&ctx,
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/type_alias.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/type_alias.rs
index de919429f..fbe120d2a 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/type_alias.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/type_alias.rs
@@ -40,7 +40,7 @@ fn render(
};
let detail = type_alias.display(db).to_string();
- let mut item = CompletionItem::new(SymbolKind::TypeAlias, ctx.source_range(), name.clone());
+ let mut item = CompletionItem::new(SymbolKind::TypeAlias, ctx.source_range(), name);
item.set_documentation(ctx.docs(type_alias))
.set_deprecated(ctx.is_deprecated(type_alias) || ctx.is_deprecated_assoc_item(type_alias))
.detail(detail)
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs
index 54e97dd57..1b09ad173 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs
@@ -24,7 +24,7 @@ pub(crate) fn render_union_literal(
Some(p) => (p.unescaped().to_string(), p.to_string()),
None => (name.unescaped().to_string(), name.to_string()),
};
- let label = format_literal_label(&name.to_smol_str(), StructKind::Record);
+ let label = format_literal_label(&name.to_smol_str(), StructKind::Record, ctx.snippet_cap());
let lookup = format_literal_lookup(&name.to_smol_str(), StructKind::Record);
let mut item = CompletionItem::new(
CompletionItemKind::SymbolKind(SymbolKind::Union),
@@ -68,7 +68,7 @@ pub(crate) fn render_union_literal(
item.set_documentation(ctx.docs(un))
.set_deprecated(ctx.is_deprecated(un))
- .detail(&detail)
+ .detail(detail)
.set_relevance(ctx.completion_relevance());
match ctx.snippet_cap() {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/variant.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/variant.rs
index 24e6abdc9..55c55725b 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/variant.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/variant.rs
@@ -22,6 +22,9 @@ pub(crate) fn render_record_lit(
fields: &[hir::Field],
path: &str,
) -> RenderedLiteral {
+ if snippet_cap.is_none() {
+ return RenderedLiteral { literal: path.to_string(), detail: path.to_string() };
+ }
let completions = fields.iter().enumerate().format_with(", ", |(idx, field), f| {
if snippet_cap.is_some() {
f(&format_args!("{}: ${{{}:()}}", field.name(db), idx + 1))
@@ -35,8 +38,8 @@ pub(crate) fn render_record_lit(
});
RenderedLiteral {
- literal: format!("{} {{ {} }}", path, completions),
- detail: format!("{} {{ {} }}", path, types),
+ literal: format!("{path} {{ {completions} }}"),
+ detail: format!("{path} {{ {types} }}"),
}
}
@@ -48,6 +51,9 @@ pub(crate) fn render_tuple_lit(
fields: &[hir::Field],
path: &str,
) -> RenderedLiteral {
+ if snippet_cap.is_none() {
+ return RenderedLiteral { literal: path.to_string(), detail: path.to_string() };
+ }
let completions = fields.iter().enumerate().format_with(", ", |(idx, _), f| {
if snippet_cap.is_some() {
f(&format_args!("${{{}:()}}", idx + 1))
@@ -59,8 +65,8 @@ pub(crate) fn render_tuple_lit(
let types = fields.iter().format_with(", ", |field, f| f(&field.ty(db).display(db)));
RenderedLiteral {
- literal: format!("{}({})", path, completions),
- detail: format!("{}({})", path, types),
+ literal: format!("{path}({completions})"),
+ detail: format!("{path}({types})"),
}
}
@@ -87,7 +93,14 @@ pub(crate) fn visible_fields(
}
/// Format a struct, etc. literal option for display in the completions menu.
-pub(crate) fn format_literal_label(name: &str, kind: StructKind) -> SmolStr {
+pub(crate) fn format_literal_label(
+ name: &str,
+ kind: StructKind,
+ snippet_cap: Option<SnippetCap>,
+) -> SmolStr {
+ if snippet_cap.is_none() {
+ return name.into();
+ }
match kind {
StructKind::Tuple => SmolStr::from_iter([name, "(…)"]),
StructKind::Record => SmolStr::from_iter([name, " {…}"]),
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 f3b8eae4f..343719c53 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs
@@ -199,7 +199,7 @@ fn validate_snippet(
) -> Option<(Box<[GreenNode]>, String, Option<Box<str>>)> {
let mut imports = Vec::with_capacity(requires.len());
for path in requires.iter() {
- let use_path = ast::SourceFile::parse(&format!("use {};", path))
+ let use_path = ast::SourceFile::parse(&format!("use {path};"))
.syntax_node()
.descendants()
.find_map(ast::Path::cast)?;
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 9e2beb9ee..abe14e48e 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
@@ -86,7 +86,7 @@ pub(crate) fn completion_list_no_kw(ra_fixture: &str) -> String {
}
pub(crate) fn completion_list_no_kw_with_private_editable(ra_fixture: &str) -> String {
- let mut config = TEST_CONFIG.clone();
+ let mut config = TEST_CONFIG;
config.enable_private_editable = true;
completion_list_with_config(config, ra_fixture, false, None)
}
@@ -153,7 +153,7 @@ fn render_completion_list(completions: Vec<CompletionItem>) -> String {
.into_iter()
.map(|it| {
let tag = it.kind().tag();
- let var_name = format!("{} {}", tag, it.label());
+ let var_name = format!("{tag} {}", it.label());
let mut buf = var_name;
if let Some(detail) = it.detail() {
let width = label_width.saturating_sub(monospace_width(it.label()));
@@ -183,12 +183,12 @@ pub(crate) fn check_edit_with_config(
let ra_fixture_after = trim_indent(ra_fixture_after);
let (db, position) = position(ra_fixture_before);
let completions: Vec<CompletionItem> =
- crate::completions(&db, &config, position, None).unwrap().into();
+ crate::completions(&db, &config, position, None).unwrap();
let (completion,) = completions
.iter()
.filter(|it| it.lookup() == what)
.collect_tuple()
- .unwrap_or_else(|| panic!("can't find {:?} completion in {:#?}", what, completions));
+ .unwrap_or_else(|| panic!("can't find {what:?} completion in {completions:#?}"));
let mut actual = db.file_text(position.file_id).to_string();
let mut combined_edit = completion.text_edit().to_owned();
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs
index 1578ba2c3..4e60820dd 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs
@@ -607,6 +607,30 @@ fn attr_in_source_file_end() {
);
}
+#[test]
+fn invalid_path() {
+ check(
+ r#"
+//- proc_macros: identity
+#[proc_macros:::$0]
+struct Foo;
+"#,
+ expect![[r#""#]],
+ );
+
+ check(
+ r#"
+//- minicore: derive, copy
+mod foo {
+ pub use Copy as Bar;
+}
+#[derive(foo:::::$0)]
+struct Foo;
+"#,
+ expect![""],
+ );
+}
+
mod cfg {
use super::*;
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 8e26d889f..043f552bd 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
@@ -4,7 +4,7 @@ use expect_test::{expect, Expect};
use crate::tests::{check_edit, completion_list, BASE_ITEMS_FIXTURE};
fn check(ra_fixture: &str, expect: Expect) {
- let actual = completion_list(&format!("{}{}", BASE_ITEMS_FIXTURE, ra_fixture));
+ let actual = completion_list(&format!("{BASE_ITEMS_FIXTURE}{ra_fixture}"));
expect.assert_eq(&actual)
}
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 409413c1d..3ef2a7c94 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
@@ -7,7 +7,7 @@ use expect_test::{expect, Expect};
use crate::tests::{completion_list, BASE_ITEMS_FIXTURE};
fn check(ra_fixture: &str, expect: Expect) {
- let actual = completion_list(&format!("{}{}", BASE_ITEMS_FIXTURE, ra_fixture));
+ let actual = completion_list(&format!("{BASE_ITEMS_FIXTURE}{ra_fixture}"));
expect.assert_eq(&actual)
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs
index 8ed6cb3cf..b62b98888 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs
@@ -1,10 +1,10 @@
//! Completion tests for item list position.
use expect_test::{expect, Expect};
-use crate::tests::{completion_list, BASE_ITEMS_FIXTURE};
+use crate::tests::{check_edit, completion_list, BASE_ITEMS_FIXTURE};
fn check(ra_fixture: &str, expect: Expect) {
- let actual = completion_list(&format!("{}{}", BASE_ITEMS_FIXTURE, ra_fixture));
+ let actual = completion_list(&format!("{BASE_ITEMS_FIXTURE}{ra_fixture}"));
expect.assert_eq(&actual)
}
@@ -277,3 +277,91 @@ fn after_unit_struct() {
"#]],
);
}
+
+#[test]
+fn type_in_impl_trait() {
+ check_edit(
+ "type O",
+ r"
+struct A;
+trait B {
+type O: ?Sized;
+}
+impl B for A {
+$0
+}
+",
+ r#"
+struct A;
+trait B {
+type O: ?Sized;
+}
+impl B for A {
+type O = $0;
+}
+"#,
+ );
+ check_edit(
+ "type O",
+ r"
+struct A;
+trait B {
+type O;
+}
+impl B for A {
+$0
+}
+",
+ r#"
+struct A;
+trait B {
+type O;
+}
+impl B for A {
+type O = $0;
+}
+"#,
+ );
+ check_edit(
+ "type O",
+ r"
+struct A;
+trait B {
+type O: ?Sized = u32;
+}
+impl B for A {
+$0
+}
+",
+ r#"
+struct A;
+trait B {
+type O: ?Sized = u32;
+}
+impl B for A {
+type O = $0;
+}
+"#,
+ );
+ check_edit(
+ "type O",
+ r"
+struct A;
+trait B {
+type O = u32;
+}
+impl B for A {
+$0
+}
+",
+ r"
+struct A;
+trait B {
+type O = u32;
+}
+impl B for A {
+type O = $0;
+}
+",
+ )
+}
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 db8bef664..ad9254e7f 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
@@ -9,7 +9,7 @@ fn check_empty(ra_fixture: &str, expect: Expect) {
}
fn check(ra_fixture: &str, expect: Expect) {
- let actual = completion_list(&format!("{}\n{}", BASE_ITEMS_FIXTURE, ra_fixture));
+ let actual = completion_list(&format!("{BASE_ITEMS_FIXTURE}\n{ra_fixture}"));
expect.assert_eq(&actual)
}
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 a8676e2f2..2656a4d54 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
@@ -4,7 +4,7 @@ use expect_test::{expect, Expect};
use crate::tests::{completion_list, BASE_ITEMS_FIXTURE};
fn check(ra_fixture: &str, expect: Expect) {
- let actual = completion_list(&format!("{}\n{}", BASE_ITEMS_FIXTURE, ra_fixture));
+ let actual = completion_list(&format!("{BASE_ITEMS_FIXTURE}\n{ra_fixture}"));
expect.assert_eq(&actual)
}
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 033dc99c2..cad4af493 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,13 +2,22 @@
use expect_test::{expect, Expect};
-use crate::tests::{check_edit, completion_list_no_kw};
+use crate::tests::{check_edit, completion_list_no_kw, completion_list_with_trigger_character};
fn check(ra_fixture: &str, expect: Expect) {
let actual = completion_list_no_kw(ra_fixture);
expect.assert_eq(&actual)
}
+pub(crate) fn check_with_trigger_character(
+ ra_fixture: &str,
+ trigger_character: Option<char>,
+ expect: Expect,
+) {
+ let actual = completion_list_with_trigger_character(ra_fixture, trigger_character);
+ expect.assert_eq(&actual)
+}
+
#[test]
fn completes_if_prefix_is_keyword() {
check_edit(
@@ -893,3 +902,82 @@ fn f() {
"#]],
);
}
+
+#[test]
+fn completes_after_colon_with_trigger() {
+ check_with_trigger_character(
+ r#"
+//- minicore: option
+fn foo { ::$0 }
+"#,
+ Some(':'),
+ expect![[r#"
+ md core
+ "#]],
+ );
+ check_with_trigger_character(
+ r#"
+//- minicore: option
+fn foo { /* test */::$0 }
+"#,
+ Some(':'),
+ expect![[r#"
+ md core
+ "#]],
+ );
+
+ check_with_trigger_character(
+ r#"
+fn foo { crate::$0 }
+"#,
+ Some(':'),
+ expect![[r#"
+ fn foo() fn()
+ "#]],
+ );
+
+ check_with_trigger_character(
+ r#"
+fn foo { crate:$0 }
+"#,
+ Some(':'),
+ expect![""],
+ );
+}
+
+#[test]
+fn completes_after_colon_without_trigger() {
+ check_with_trigger_character(
+ r#"
+fn foo { crate::$0 }
+"#,
+ None,
+ expect![[r#"
+ fn foo() fn()
+ "#]],
+ );
+
+ check_with_trigger_character(
+ r#"
+fn foo { crate:$0 }
+"#,
+ None,
+ expect![""],
+ );
+}
+
+#[test]
+fn no_completions_in_invalid_path() {
+ check(
+ r#"
+fn foo { crate:::$0 }
+"#,
+ expect![""],
+ );
+ check(
+ r#"
+fn foo { crate::::$0 }
+"#,
+ expect![""],
+ )
+}
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 f0b7726c5..c3f4fb4d1 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
@@ -4,7 +4,7 @@ use expect_test::{expect, Expect};
use crate::tests::{completion_list, BASE_ITEMS_FIXTURE};
fn check(ra_fixture: &str, expect: Expect) {
- let actual = completion_list(&format!("{}\n{}", BASE_ITEMS_FIXTURE, ra_fixture));
+ let actual = completion_list(&format!("{BASE_ITEMS_FIXTURE}\n{ra_fixture}"));
expect.assert_eq(&actual)
}