mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-11-19 11:35:16 +00:00
cargo clippy --fix
This commit is contained in:
parent
423c7dd23a
commit
8ce30264c8
186 changed files with 3056 additions and 3314 deletions
|
|
@ -111,10 +111,11 @@ impl Completions {
|
|||
ctx: &CompletionContext<'_>,
|
||||
super_chain_len: Option<usize>,
|
||||
) {
|
||||
if let Some(len) = super_chain_len {
|
||||
if len > 0 && len < ctx.depth_from_crate_root {
|
||||
self.add_keyword(ctx, "super::");
|
||||
}
|
||||
if let Some(len) = super_chain_len
|
||||
&& len > 0
|
||||
&& len < ctx.depth_from_crate_root
|
||||
{
|
||||
self.add_keyword(ctx, "super::");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -643,10 +644,10 @@ fn enum_variants_with_paths(
|
|||
|
||||
let variants = enum_.variants(ctx.db);
|
||||
|
||||
if let Some(impl_) = impl_.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) {
|
||||
if impl_.self_ty(ctx.db).as_adt() == Some(hir::Adt::Enum(enum_)) {
|
||||
variants.iter().for_each(|variant| process_variant(*variant));
|
||||
}
|
||||
if let Some(impl_) = impl_.as_ref().and_then(|impl_| ctx.sema.to_def(impl_))
|
||||
&& impl_.self_ty(ctx.db).as_adt() == Some(hir::Adt::Enum(enum_))
|
||||
{
|
||||
variants.iter().for_each(|variant| process_variant(*variant));
|
||||
}
|
||||
|
||||
for variant in variants {
|
||||
|
|
|
|||
|
|
@ -258,12 +258,11 @@ fn complete_methods(
|
|||
fn on_trait_method(&mut self, func: hir::Function) -> ControlFlow<()> {
|
||||
// This needs to come before the `seen_methods` test, so that if we see the same method twice,
|
||||
// once as inherent and once not, we will include it.
|
||||
if let ItemContainer::Trait(trait_) = func.container(self.ctx.db) {
|
||||
if self.ctx.exclude_traits.contains(&trait_)
|
||||
|| trait_.complete(self.ctx.db) == Complete::IgnoreMethods
|
||||
{
|
||||
return ControlFlow::Continue(());
|
||||
}
|
||||
if let ItemContainer::Trait(trait_) = func.container(self.ctx.db)
|
||||
&& (self.ctx.exclude_traits.contains(&trait_)
|
||||
|| trait_.complete(self.ctx.db) == Complete::IgnoreMethods)
|
||||
{
|
||||
return ControlFlow::Continue(());
|
||||
}
|
||||
|
||||
if func.self_param(self.ctx.db).is_some()
|
||||
|
|
|
|||
|
|
@ -128,10 +128,10 @@ fn params_from_stmt_list_scope(
|
|||
{
|
||||
let module = scope.module().into();
|
||||
scope.process_all_names(&mut |name, def| {
|
||||
if let hir::ScopeDef::Local(local) = def {
|
||||
if let Ok(ty) = local.ty(ctx.db).display_source_code(ctx.db, module, true) {
|
||||
cb(name, ty);
|
||||
}
|
||||
if let hir::ScopeDef::Local(local) = def
|
||||
&& let Ok(ty) = local.ty(ctx.db).display_source_code(ctx.db, module, true)
|
||||
{
|
||||
cb(name, ty);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -228,24 +228,22 @@ fn add_function_impl_(
|
|||
.set_documentation(func.docs(ctx.db))
|
||||
.set_relevance(CompletionRelevance { exact_name_match: true, ..Default::default() });
|
||||
|
||||
if let Some(source) = ctx.sema.source(func) {
|
||||
if let Some(transformed_fn) =
|
||||
if let Some(source) = ctx.sema.source(func)
|
||||
&& let Some(transformed_fn) =
|
||||
get_transformed_fn(ctx, source.value, impl_def, async_sugaring)
|
||||
{
|
||||
let function_decl =
|
||||
function_declaration(ctx, &transformed_fn, source.file_id.macro_file());
|
||||
match ctx.config.snippet_cap {
|
||||
Some(cap) => {
|
||||
let snippet = format!("{function_decl} {{\n $0\n}}");
|
||||
item.snippet_edit(cap, TextEdit::replace(replacement_range, snippet));
|
||||
}
|
||||
None => {
|
||||
let header = format!("{function_decl} {{");
|
||||
item.text_edit(TextEdit::replace(replacement_range, header));
|
||||
}
|
||||
};
|
||||
item.add_to(acc, ctx.db);
|
||||
}
|
||||
{
|
||||
let function_decl = function_declaration(ctx, &transformed_fn, source.file_id.macro_file());
|
||||
match ctx.config.snippet_cap {
|
||||
Some(cap) => {
|
||||
let snippet = format!("{function_decl} {{\n $0\n}}");
|
||||
item.snippet_edit(cap, TextEdit::replace(replacement_range, snippet));
|
||||
}
|
||||
None => {
|
||||
let header = format!("{function_decl} {{");
|
||||
item.text_edit(TextEdit::replace(replacement_range, header));
|
||||
}
|
||||
};
|
||||
item.add_to(acc, ctx.db);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -447,36 +445,36 @@ fn add_const_impl(
|
|||
) {
|
||||
let const_name = const_.name(ctx.db).map(|n| n.display_no_db(ctx.edition).to_smolstr());
|
||||
|
||||
if let Some(const_name) = const_name {
|
||||
if let Some(source) = ctx.sema.source(const_) {
|
||||
let assoc_item = ast::AssocItem::Const(source.value);
|
||||
if let Some(transformed_item) = get_transformed_assoc_item(ctx, assoc_item, impl_def) {
|
||||
let transformed_const = match transformed_item {
|
||||
ast::AssocItem::Const(const_) => const_,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
if let Some(const_name) = const_name
|
||||
&& let Some(source) = ctx.sema.source(const_)
|
||||
{
|
||||
let assoc_item = ast::AssocItem::Const(source.value);
|
||||
if let Some(transformed_item) = get_transformed_assoc_item(ctx, assoc_item, impl_def) {
|
||||
let transformed_const = match transformed_item {
|
||||
ast::AssocItem::Const(const_) => const_,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let label =
|
||||
make_const_compl_syntax(ctx, &transformed_const, source.file_id.macro_file());
|
||||
let replacement = format!("{label} ");
|
||||
let label =
|
||||
make_const_compl_syntax(ctx, &transformed_const, source.file_id.macro_file());
|
||||
let replacement = format!("{label} ");
|
||||
|
||||
let mut item =
|
||||
CompletionItem::new(SymbolKind::Const, replacement_range, label, ctx.edition);
|
||||
item.lookup_by(format_smolstr!("const {const_name}"))
|
||||
.set_documentation(const_.docs(ctx.db))
|
||||
.set_relevance(CompletionRelevance {
|
||||
exact_name_match: true,
|
||||
..Default::default()
|
||||
});
|
||||
match ctx.config.snippet_cap {
|
||||
Some(cap) => item.snippet_edit(
|
||||
cap,
|
||||
TextEdit::replace(replacement_range, format!("{replacement}$0;")),
|
||||
),
|
||||
None => item.text_edit(TextEdit::replace(replacement_range, replacement)),
|
||||
};
|
||||
item.add_to(acc, ctx.db);
|
||||
}
|
||||
let mut item =
|
||||
CompletionItem::new(SymbolKind::Const, replacement_range, label, ctx.edition);
|
||||
item.lookup_by(format_smolstr!("const {const_name}"))
|
||||
.set_documentation(const_.docs(ctx.db))
|
||||
.set_relevance(CompletionRelevance {
|
||||
exact_name_match: true,
|
||||
..Default::default()
|
||||
});
|
||||
match ctx.config.snippet_cap {
|
||||
Some(cap) => item.snippet_edit(
|
||||
cap,
|
||||
TextEdit::replace(replacement_range, format!("{replacement}$0;")),
|
||||
),
|
||||
None => item.text_edit(TextEdit::replace(replacement_range, replacement)),
|
||||
};
|
||||
item.add_to(acc, ctx.db);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,18 +26,17 @@ pub(crate) fn complete_mod(
|
|||
let mut current_module = ctx.module;
|
||||
// For `mod $0`, `ctx.module` is its parent, but for `mod f$0`, it's `mod f` itself, but we're
|
||||
// interested in its parent.
|
||||
if ctx.original_token.kind() == SyntaxKind::IDENT {
|
||||
if let Some(module) =
|
||||
if ctx.original_token.kind() == SyntaxKind::IDENT
|
||||
&& let Some(module) =
|
||||
ctx.original_token.parent_ancestors().nth(1).and_then(ast::Module::cast)
|
||||
{
|
||||
match ctx.sema.to_def(&module) {
|
||||
Some(module) if module == current_module => {
|
||||
if let Some(parent) = current_module.parent(ctx.db) {
|
||||
current_module = parent;
|
||||
}
|
||||
{
|
||||
match ctx.sema.to_def(&module) {
|
||||
Some(module) if module == current_module => {
|
||||
if let Some(parent) = current_module.parent(ctx.db) {
|
||||
current_module = parent;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,18 +64,17 @@ pub(crate) fn complete_pattern(
|
|||
|
||||
if let Some(hir::Adt::Enum(e)) =
|
||||
ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt())
|
||||
&& (refutable || single_variant_enum(e))
|
||||
{
|
||||
if refutable || single_variant_enum(e) {
|
||||
super::enum_variants_with_paths(
|
||||
acc,
|
||||
ctx,
|
||||
e,
|
||||
&pattern_ctx.impl_,
|
||||
|acc, ctx, variant, path| {
|
||||
acc.add_qualified_variant_pat(ctx, pattern_ctx, variant, path);
|
||||
},
|
||||
);
|
||||
}
|
||||
super::enum_variants_with_paths(
|
||||
acc,
|
||||
ctx,
|
||||
e,
|
||||
&pattern_ctx.impl_,
|
||||
|acc, ctx, variant, path| {
|
||||
acc.add_qualified_variant_pat(ctx, pattern_ctx, variant, path);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// FIXME: ideally, we should look at the type we are matching against and
|
||||
|
|
|
|||
|
|
@ -65,26 +65,19 @@ pub(crate) fn complete_postfix(
|
|||
|
||||
let cfg = ctx.config.import_path_config(ctx.is_nightly);
|
||||
|
||||
if let Some(drop_trait) = ctx.famous_defs().core_ops_Drop() {
|
||||
if receiver_ty.impls_trait(ctx.db, drop_trait, &[]) {
|
||||
if let Some(drop_fn) = ctx.famous_defs().core_mem_drop() {
|
||||
if let Some(path) =
|
||||
ctx.module.find_path(ctx.db, ItemInNs::Values(drop_fn.into()), cfg)
|
||||
{
|
||||
cov_mark::hit!(postfix_drop_completion);
|
||||
let mut item = postfix_snippet(
|
||||
"drop",
|
||||
"fn drop(&mut self)",
|
||||
&format!(
|
||||
"{path}($0{receiver_text})",
|
||||
path = path.display(ctx.db, ctx.edition)
|
||||
),
|
||||
);
|
||||
item.set_documentation(drop_fn.docs(ctx.db));
|
||||
item.add_to(acc, ctx.db);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(drop_trait) = ctx.famous_defs().core_ops_Drop()
|
||||
&& receiver_ty.impls_trait(ctx.db, drop_trait, &[])
|
||||
&& let Some(drop_fn) = ctx.famous_defs().core_mem_drop()
|
||||
&& let Some(path) = ctx.module.find_path(ctx.db, ItemInNs::Values(drop_fn.into()), cfg)
|
||||
{
|
||||
cov_mark::hit!(postfix_drop_completion);
|
||||
let mut item = postfix_snippet(
|
||||
"drop",
|
||||
"fn drop(&mut self)",
|
||||
&format!("{path}($0{receiver_text})", path = path.display(ctx.db, ctx.edition)),
|
||||
);
|
||||
item.set_documentation(drop_fn.docs(ctx.db));
|
||||
item.add_to(acc, ctx.db);
|
||||
}
|
||||
|
||||
postfix_snippet("ref", "&expr", &format!("&{receiver_text}")).add_to(acc, ctx.db);
|
||||
|
|
@ -117,56 +110,50 @@ pub(crate) fn complete_postfix(
|
|||
|
||||
let try_enum = TryEnum::from_ty(&ctx.sema, &receiver_ty.strip_references());
|
||||
let mut is_in_cond = false;
|
||||
if let Some(parent) = dot_receiver_including_refs.syntax().parent() {
|
||||
if let Some(second_ancestor) = parent.parent() {
|
||||
let sec_ancestor_kind = second_ancestor.kind();
|
||||
if let Some(expr) = <Either<ast::IfExpr, ast::WhileExpr>>::cast(second_ancestor) {
|
||||
is_in_cond = match expr {
|
||||
Either::Left(it) => it.condition().is_some_and(|cond| *cond.syntax() == parent),
|
||||
Either::Right(it) => {
|
||||
it.condition().is_some_and(|cond| *cond.syntax() == parent)
|
||||
}
|
||||
}
|
||||
if let Some(parent) = dot_receiver_including_refs.syntax().parent()
|
||||
&& let Some(second_ancestor) = parent.parent()
|
||||
{
|
||||
let sec_ancestor_kind = second_ancestor.kind();
|
||||
if let Some(expr) = <Either<ast::IfExpr, ast::WhileExpr>>::cast(second_ancestor) {
|
||||
is_in_cond = match expr {
|
||||
Either::Left(it) => it.condition().is_some_and(|cond| *cond.syntax() == parent),
|
||||
Either::Right(it) => it.condition().is_some_and(|cond| *cond.syntax() == parent),
|
||||
}
|
||||
match &try_enum {
|
||||
Some(try_enum) if is_in_cond => match try_enum {
|
||||
TryEnum::Result => {
|
||||
postfix_snippet(
|
||||
"let",
|
||||
"let Ok(_)",
|
||||
&format!("let Ok($0) = {receiver_text}"),
|
||||
)
|
||||
.add_to(acc, ctx.db);
|
||||
postfix_snippet(
|
||||
"letm",
|
||||
"let Ok(mut _)",
|
||||
&format!("let Ok(mut $0) = {receiver_text}"),
|
||||
)
|
||||
.add_to(acc, ctx.db);
|
||||
}
|
||||
TryEnum::Option => {
|
||||
postfix_snippet(
|
||||
"let",
|
||||
"let Some(_)",
|
||||
&format!("let Some($0) = {receiver_text}"),
|
||||
)
|
||||
.add_to(acc, ctx.db);
|
||||
postfix_snippet(
|
||||
"letm",
|
||||
"let Some(mut _)",
|
||||
&format!("let Some(mut $0) = {receiver_text}"),
|
||||
)
|
||||
.add_to(acc, ctx.db);
|
||||
}
|
||||
},
|
||||
_ if matches!(sec_ancestor_kind, STMT_LIST | EXPR_STMT) => {
|
||||
postfix_snippet("let", "let", &format!("let $0 = {receiver_text};"))
|
||||
.add_to(acc, ctx.db);
|
||||
postfix_snippet("letm", "let mut", &format!("let mut $0 = {receiver_text};"))
|
||||
}
|
||||
match &try_enum {
|
||||
Some(try_enum) if is_in_cond => match try_enum {
|
||||
TryEnum::Result => {
|
||||
postfix_snippet("let", "let Ok(_)", &format!("let Ok($0) = {receiver_text}"))
|
||||
.add_to(acc, ctx.db);
|
||||
postfix_snippet(
|
||||
"letm",
|
||||
"let Ok(mut _)",
|
||||
&format!("let Ok(mut $0) = {receiver_text}"),
|
||||
)
|
||||
.add_to(acc, ctx.db);
|
||||
}
|
||||
_ => (),
|
||||
TryEnum::Option => {
|
||||
postfix_snippet(
|
||||
"let",
|
||||
"let Some(_)",
|
||||
&format!("let Some($0) = {receiver_text}"),
|
||||
)
|
||||
.add_to(acc, ctx.db);
|
||||
postfix_snippet(
|
||||
"letm",
|
||||
"let Some(mut _)",
|
||||
&format!("let Some(mut $0) = {receiver_text}"),
|
||||
)
|
||||
.add_to(acc, ctx.db);
|
||||
}
|
||||
},
|
||||
_ if matches!(sec_ancestor_kind, STMT_LIST | EXPR_STMT) => {
|
||||
postfix_snippet("let", "let", &format!("let $0 = {receiver_text};"))
|
||||
.add_to(acc, ctx.db);
|
||||
postfix_snippet("letm", "let mut", &format!("let mut $0 = {receiver_text};"))
|
||||
.add_to(acc, ctx.db);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -258,25 +245,25 @@ pub(crate) fn complete_postfix(
|
|||
)
|
||||
.add_to(acc, ctx.db);
|
||||
postfix_snippet("not", "!expr", &format!("!{receiver_text}")).add_to(acc, ctx.db);
|
||||
} 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 {receiver_text} {{\n $0\n}}"),
|
||||
)
|
||||
.add_to(acc, ctx.db);
|
||||
}
|
||||
} else if let Some(trait_) = ctx.famous_defs().core_iter_IntoIterator()
|
||||
&& receiver_ty.impls_trait(ctx.db, trait_, &[])
|
||||
{
|
||||
postfix_snippet(
|
||||
"for",
|
||||
"for ele in expr {}",
|
||||
&format!("for ele in {receiver_text} {{\n $0\n}}"),
|
||||
)
|
||||
.add_to(acc, ctx.db);
|
||||
}
|
||||
}
|
||||
|
||||
let mut block_should_be_wrapped = true;
|
||||
if dot_receiver.syntax().kind() == BLOCK_EXPR {
|
||||
block_should_be_wrapped = false;
|
||||
if let Some(parent) = dot_receiver.syntax().parent() {
|
||||
if matches!(parent.kind(), IF_EXPR | WHILE_EXPR | LOOP_EXPR | FOR_EXPR) {
|
||||
block_should_be_wrapped = true;
|
||||
}
|
||||
if let Some(parent) = dot_receiver.syntax().parent()
|
||||
&& matches!(parent.kind(), IF_EXPR | WHILE_EXPR | LOOP_EXPR | FOR_EXPR)
|
||||
{
|
||||
block_should_be_wrapped = true;
|
||||
}
|
||||
};
|
||||
{
|
||||
|
|
@ -292,10 +279,10 @@ pub(crate) fn complete_postfix(
|
|||
postfix_snippet("const", "const {}", &const_completion_string).add_to(acc, ctx.db);
|
||||
}
|
||||
|
||||
if let ast::Expr::Literal(literal) = dot_receiver_including_refs.clone() {
|
||||
if let Some(literal_text) = ast::String::cast(literal.token()) {
|
||||
add_format_like_completions(acc, ctx, &dot_receiver_including_refs, cap, &literal_text);
|
||||
}
|
||||
if let ast::Expr::Literal(literal) = dot_receiver_including_refs.clone()
|
||||
&& let Some(literal_text) = ast::String::cast(literal.token())
|
||||
{
|
||||
add_format_like_completions(acc, ctx, &dot_receiver_including_refs, cap, &literal_text);
|
||||
}
|
||||
|
||||
postfix_snippet(
|
||||
|
|
|
|||
|
|
@ -54,12 +54,10 @@ pub(crate) fn complete_use_path(
|
|||
for (name, def) in module_scope {
|
||||
if let (Some(attrs), Some(defining_crate)) =
|
||||
(def.attrs(ctx.db), def.krate(ctx.db))
|
||||
&& (!ctx.check_stability(Some(&attrs))
|
||||
|| ctx.is_doc_hidden(&attrs, defining_crate))
|
||||
{
|
||||
if !ctx.check_stability(Some(&attrs))
|
||||
|| ctx.is_doc_hidden(&attrs, defining_crate)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
let is_name_already_imported =
|
||||
already_imported_names.contains(name.as_str());
|
||||
|
|
|
|||
|
|
@ -20,11 +20,11 @@ pub(crate) fn complete_vis_path(
|
|||
// Try completing next child module of the path that is still a parent of the current module
|
||||
let next_towards_current =
|
||||
ctx.module.path_to_root(ctx.db).into_iter().take_while(|it| it != module).last();
|
||||
if let Some(next) = next_towards_current {
|
||||
if let Some(name) = next.name(ctx.db) {
|
||||
cov_mark::hit!(visibility_qualified);
|
||||
acc.add_module(ctx, path_ctx, next, name, vec![]);
|
||||
}
|
||||
if let Some(next) = next_towards_current
|
||||
&& let Some(name) = next.name(ctx.db)
|
||||
{
|
||||
cov_mark::hit!(visibility_qualified);
|
||||
acc.add_module(ctx, path_ctx, next, name, vec![]);
|
||||
}
|
||||
|
||||
acc.add_super_keyword(ctx, *super_chain_len);
|
||||
|
|
|
|||
|
|
@ -287,24 +287,22 @@ fn expand(
|
|||
&spec_attr,
|
||||
fake_ident_token.clone(),
|
||||
),
|
||||
) {
|
||||
if let Some((fake_mapped_token, _)) =
|
||||
fake_mapped_tokens.into_iter().min_by_key(|(_, rank)| *rank)
|
||||
{
|
||||
return Some(ExpansionResult {
|
||||
original_file: original_file.value,
|
||||
speculative_file,
|
||||
original_offset,
|
||||
speculative_offset: fake_ident_token.text_range().start(),
|
||||
fake_ident_token,
|
||||
derive_ctx: Some((
|
||||
actual_expansion,
|
||||
fake_expansion,
|
||||
fake_mapped_token.text_range().start(),
|
||||
orig_attr,
|
||||
)),
|
||||
});
|
||||
}
|
||||
) && let Some((fake_mapped_token, _)) =
|
||||
fake_mapped_tokens.into_iter().min_by_key(|(_, rank)| *rank)
|
||||
{
|
||||
return Some(ExpansionResult {
|
||||
original_file: original_file.value,
|
||||
speculative_file,
|
||||
original_offset,
|
||||
speculative_offset: fake_ident_token.text_range().start(),
|
||||
fake_ident_token,
|
||||
derive_ctx: Some((
|
||||
actual_expansion,
|
||||
fake_expansion,
|
||||
fake_mapped_token.text_range().start(),
|
||||
orig_attr,
|
||||
)),
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(spec_adt) =
|
||||
|
|
@ -535,14 +533,13 @@ fn analyze<'db>(
|
|||
NameRefKind::Path(PathCompletionCtx { kind: PathKind::Expr { .. }, path, .. }, ..),
|
||||
..
|
||||
} = &nameref_ctx
|
||||
&& is_in_token_of_for_loop(path)
|
||||
{
|
||||
if is_in_token_of_for_loop(path) {
|
||||
// for pat $0
|
||||
// there is nothing to complete here except `in` keyword
|
||||
// don't bother populating the context
|
||||
// Ideally this special casing wouldn't be needed, but the parser recovers
|
||||
return None;
|
||||
}
|
||||
// for pat $0
|
||||
// there is nothing to complete here except `in` keyword
|
||||
// don't bother populating the context
|
||||
// Ideally this special casing wouldn't be needed, but the parser recovers
|
||||
return None;
|
||||
}
|
||||
|
||||
qual_ctx = qualifier_ctx;
|
||||
|
|
@ -951,29 +948,26 @@ fn classify_name_ref<'db>(
|
|||
let inbetween_body_and_decl_check = |node: SyntaxNode| {
|
||||
if let Some(NodeOrToken::Node(n)) =
|
||||
syntax::algo::non_trivia_sibling(node.into(), syntax::Direction::Prev)
|
||||
&& let Some(item) = ast::Item::cast(n)
|
||||
{
|
||||
if let Some(item) = ast::Item::cast(n) {
|
||||
let is_inbetween = match &item {
|
||||
ast::Item::Const(it) => it.body().is_none() && it.semicolon_token().is_none(),
|
||||
ast::Item::Enum(it) => it.variant_list().is_none(),
|
||||
ast::Item::ExternBlock(it) => it.extern_item_list().is_none(),
|
||||
ast::Item::Fn(it) => it.body().is_none() && it.semicolon_token().is_none(),
|
||||
ast::Item::Impl(it) => it.assoc_item_list().is_none(),
|
||||
ast::Item::Module(it) => {
|
||||
it.item_list().is_none() && it.semicolon_token().is_none()
|
||||
}
|
||||
ast::Item::Static(it) => it.body().is_none(),
|
||||
ast::Item::Struct(it) => {
|
||||
it.field_list().is_none() && it.semicolon_token().is_none()
|
||||
}
|
||||
ast::Item::Trait(it) => it.assoc_item_list().is_none(),
|
||||
ast::Item::TypeAlias(it) => it.ty().is_none() && it.semicolon_token().is_none(),
|
||||
ast::Item::Union(it) => it.record_field_list().is_none(),
|
||||
_ => false,
|
||||
};
|
||||
if is_inbetween {
|
||||
return Some(item);
|
||||
let is_inbetween = match &item {
|
||||
ast::Item::Const(it) => it.body().is_none() && it.semicolon_token().is_none(),
|
||||
ast::Item::Enum(it) => it.variant_list().is_none(),
|
||||
ast::Item::ExternBlock(it) => it.extern_item_list().is_none(),
|
||||
ast::Item::Fn(it) => it.body().is_none() && it.semicolon_token().is_none(),
|
||||
ast::Item::Impl(it) => it.assoc_item_list().is_none(),
|
||||
ast::Item::Module(it) => it.item_list().is_none() && it.semicolon_token().is_none(),
|
||||
ast::Item::Static(it) => it.body().is_none(),
|
||||
ast::Item::Struct(it) => {
|
||||
it.field_list().is_none() && it.semicolon_token().is_none()
|
||||
}
|
||||
ast::Item::Trait(it) => it.assoc_item_list().is_none(),
|
||||
ast::Item::TypeAlias(it) => it.ty().is_none() && it.semicolon_token().is_none(),
|
||||
ast::Item::Union(it) => it.record_field_list().is_none(),
|
||||
_ => false,
|
||||
};
|
||||
if is_inbetween {
|
||||
return Some(item);
|
||||
}
|
||||
}
|
||||
None
|
||||
|
|
@ -1502,10 +1496,10 @@ fn classify_name_ref<'db>(
|
|||
}
|
||||
};
|
||||
}
|
||||
} else if let Some(segment) = path.segment() {
|
||||
if segment.coloncolon_token().is_some() {
|
||||
path_ctx.qualified = Qualified::Absolute;
|
||||
}
|
||||
} else if let Some(segment) = path.segment()
|
||||
&& segment.coloncolon_token().is_some()
|
||||
{
|
||||
path_ctx.qualified = Qualified::Absolute;
|
||||
}
|
||||
|
||||
let mut qualifier_ctx = QualifierCtx::default();
|
||||
|
|
@ -1530,38 +1524,30 @@ fn classify_name_ref<'db>(
|
|||
if let Some(top) = top_node {
|
||||
if let Some(NodeOrToken::Node(error_node)) =
|
||||
syntax::algo::non_trivia_sibling(top.clone().into(), syntax::Direction::Prev)
|
||||
&& error_node.kind() == SyntaxKind::ERROR
|
||||
{
|
||||
if error_node.kind() == SyntaxKind::ERROR {
|
||||
for token in
|
||||
error_node.children_with_tokens().filter_map(NodeOrToken::into_token)
|
||||
{
|
||||
match token.kind() {
|
||||
SyntaxKind::UNSAFE_KW => qualifier_ctx.unsafe_tok = Some(token),
|
||||
SyntaxKind::ASYNC_KW => qualifier_ctx.async_tok = Some(token),
|
||||
SyntaxKind::SAFE_KW => qualifier_ctx.safe_tok = Some(token),
|
||||
_ => {}
|
||||
}
|
||||
for token in error_node.children_with_tokens().filter_map(NodeOrToken::into_token) {
|
||||
match token.kind() {
|
||||
SyntaxKind::UNSAFE_KW => qualifier_ctx.unsafe_tok = Some(token),
|
||||
SyntaxKind::ASYNC_KW => qualifier_ctx.async_tok = Some(token),
|
||||
SyntaxKind::SAFE_KW => qualifier_ctx.safe_tok = Some(token),
|
||||
_ => {}
|
||||
}
|
||||
qualifier_ctx.vis_node = error_node.children().find_map(ast::Visibility::cast);
|
||||
}
|
||||
qualifier_ctx.vis_node = error_node.children().find_map(ast::Visibility::cast);
|
||||
}
|
||||
|
||||
if let PathKind::Item { .. } = path_ctx.kind {
|
||||
if qualifier_ctx.none() {
|
||||
if let Some(t) = top.first_token() {
|
||||
if let Some(prev) = t
|
||||
.prev_token()
|
||||
.and_then(|t| syntax::algo::skip_trivia_token(t, Direction::Prev))
|
||||
{
|
||||
if ![T![;], T!['}'], T!['{']].contains(&prev.kind()) {
|
||||
// This was inferred to be an item position path, but it seems
|
||||
// to be part of some other broken node which leaked into an item
|
||||
// list
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let PathKind::Item { .. } = path_ctx.kind
|
||||
&& qualifier_ctx.none()
|
||||
&& let Some(t) = top.first_token()
|
||||
&& let Some(prev) =
|
||||
t.prev_token().and_then(|t| syntax::algo::skip_trivia_token(t, Direction::Prev))
|
||||
&& ![T![;], T!['}'], T!['{']].contains(&prev.kind())
|
||||
{
|
||||
// This was inferred to be an item position path, but it seems
|
||||
// to be part of some other broken node which leaked into an item
|
||||
// list
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -636,10 +636,10 @@ impl Builder {
|
|||
}
|
||||
pub(crate) fn set_detail(&mut self, detail: Option<impl Into<String>>) -> &mut Builder {
|
||||
self.detail = detail.map(Into::into);
|
||||
if let Some(detail) = &self.detail {
|
||||
if never!(detail.contains('\n'), "multiline detail:\n{}", detail) {
|
||||
self.detail = Some(detail.split('\n').next().unwrap().to_owned());
|
||||
}
|
||||
if let Some(detail) = &self.detail
|
||||
&& never!(detail.contains('\n'), "multiline detail:\n{}", detail)
|
||||
{
|
||||
self.detail = Some(detail.split('\n').next().unwrap().to_owned());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
|
|
|||
|
|
@ -208,9 +208,9 @@ pub fn completions(
|
|||
// 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 {
|
||||
if trigger_character == Some('_')
|
||||
&& ctx.original_token.kind() == syntax::SyntaxKind::UNDERSCORE
|
||||
&& let CompletionAnalysis::NameRef(NameRefContext {
|
||||
kind:
|
||||
NameRefKind::Path(
|
||||
path_ctx @ PathCompletionCtx {
|
||||
|
|
@ -220,11 +220,9 @@ pub fn completions(
|
|||
),
|
||||
..
|
||||
}) = analysis
|
||||
{
|
||||
if path_ctx.is_trivial_path() {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
&& path_ctx.is_trivial_path()
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -164,19 +164,18 @@ pub(crate) fn render_field(
|
|||
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_owned());
|
||||
builder.insert(ctx.source_range().end(), ")".to_owned());
|
||||
if !expected_fn_type
|
||||
&& let Some(receiver) = &dot_access.receiver
|
||||
&& let Some(receiver) = ctx.completion.sema.original_ast_node(receiver.clone())
|
||||
{
|
||||
builder.insert(receiver.syntax().text_range().start(), "(".to_owned());
|
||||
builder.insert(ctx.source_range().end(), ")".to_owned());
|
||||
|
||||
let is_parens_needed =
|
||||
!matches!(dot_access.kind, DotAccessKind::Method { has_parens: true });
|
||||
let is_parens_needed =
|
||||
!matches!(dot_access.kind, DotAccessKind::Method { has_parens: true });
|
||||
|
||||
if is_parens_needed {
|
||||
builder.insert(ctx.source_range().end(), "()".to_owned());
|
||||
}
|
||||
}
|
||||
if is_parens_needed {
|
||||
builder.insert(ctx.source_range().end(), "()".to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -184,12 +183,11 @@ pub(crate) fn render_field(
|
|||
} else {
|
||||
item.insert_text(field_with_receiver(receiver.as_deref(), &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_mode) = compute_ref_match(ctx.completion, ty) {
|
||||
item.ref_match(ref_mode, original.syntax().text_range().start());
|
||||
}
|
||||
}
|
||||
if let Some(receiver) = &dot_access.receiver
|
||||
&& let Some(original) = ctx.completion.sema.original_ast_node(receiver.clone())
|
||||
&& let Some(ref_mode) = compute_ref_match(ctx.completion, ty)
|
||||
{
|
||||
item.ref_match(ref_mode, original.syntax().text_range().start());
|
||||
}
|
||||
item.doc_aliases(ctx.doc_aliases);
|
||||
item.build(db)
|
||||
|
|
@ -437,26 +435,21 @@ fn render_resolution_path(
|
|||
path_ctx,
|
||||
PathCompletionCtx { kind: PathKind::Type { .. }, has_type_args: false, .. }
|
||||
) && config.callable.is_some();
|
||||
if type_path_no_ty_args {
|
||||
if let Some(cap) = cap {
|
||||
let has_non_default_type_params = match resolution {
|
||||
ScopeDef::ModuleDef(hir::ModuleDef::Adt(it)) => it.has_non_default_type_params(db),
|
||||
ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(it)) => {
|
||||
it.has_non_default_type_params(db)
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if has_non_default_type_params {
|
||||
cov_mark::hit!(inserts_angle_brackets_for_generics);
|
||||
item.lookup_by(name.clone())
|
||||
.label(SmolStr::from_iter([&name, "<…>"]))
|
||||
.trigger_call_info()
|
||||
.insert_snippet(
|
||||
cap,
|
||||
format!("{}<$0>", local_name.display(db, completion.edition)),
|
||||
);
|
||||
if type_path_no_ty_args && let Some(cap) = cap {
|
||||
let has_non_default_type_params = match resolution {
|
||||
ScopeDef::ModuleDef(hir::ModuleDef::Adt(it)) => it.has_non_default_type_params(db),
|
||||
ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(it)) => {
|
||||
it.has_non_default_type_params(db)
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if has_non_default_type_params {
|
||||
cov_mark::hit!(inserts_angle_brackets_for_generics);
|
||||
item.lookup_by(name.clone())
|
||||
.label(SmolStr::from_iter([&name, "<…>"]))
|
||||
.trigger_call_info()
|
||||
.insert_snippet(cap, format!("{}<$0>", local_name.display(db, completion.edition)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -634,23 +627,24 @@ fn compute_ref_match(
|
|||
if expected_type.could_unify_with(ctx.db, completion_ty) {
|
||||
return None;
|
||||
}
|
||||
if let Some(expected_without_ref) = &expected_without_ref {
|
||||
if completion_ty.autoderef(ctx.db).any(|ty| ty == *expected_without_ref) {
|
||||
cov_mark::hit!(suggest_ref);
|
||||
let mutability = if expected_type.is_mutable_reference() {
|
||||
hir::Mutability::Mut
|
||||
} else {
|
||||
hir::Mutability::Shared
|
||||
};
|
||||
return Some(CompletionItemRefMode::Reference(mutability));
|
||||
}
|
||||
if let Some(expected_without_ref) = &expected_without_ref
|
||||
&& completion_ty.autoderef(ctx.db).any(|ty| ty == *expected_without_ref)
|
||||
{
|
||||
cov_mark::hit!(suggest_ref);
|
||||
let mutability = if expected_type.is_mutable_reference() {
|
||||
hir::Mutability::Mut
|
||||
} else {
|
||||
hir::Mutability::Shared
|
||||
};
|
||||
return Some(CompletionItemRefMode::Reference(mutability));
|
||||
}
|
||||
|
||||
if let Some(completion_without_ref) = completion_without_ref {
|
||||
if completion_without_ref == *expected_type && completion_without_ref.is_copy(ctx.db) {
|
||||
cov_mark::hit!(suggest_deref);
|
||||
return Some(CompletionItemRefMode::Dereference);
|
||||
}
|
||||
if let Some(completion_without_ref) = completion_without_ref
|
||||
&& completion_without_ref == *expected_type
|
||||
&& completion_without_ref.is_copy(ctx.db)
|
||||
{
|
||||
cov_mark::hit!(suggest_deref);
|
||||
return Some(CompletionItemRefMode::Dereference);
|
||||
}
|
||||
|
||||
None
|
||||
|
|
@ -664,10 +658,10 @@ fn path_ref_match(
|
|||
) {
|
||||
if let Some(original_path) = &path_ctx.original_path {
|
||||
// At least one char was typed by the user already, in that case look for the original path
|
||||
if let Some(original_path) = completion.sema.original_ast_node(original_path.clone()) {
|
||||
if let Some(ref_mode) = compute_ref_match(completion, ty) {
|
||||
item.ref_match(ref_mode, original_path.syntax().text_range().start());
|
||||
}
|
||||
if let Some(original_path) = completion.sema.original_ast_node(original_path.clone())
|
||||
&& let Some(ref_mode) = compute_ref_match(completion, ty)
|
||||
{
|
||||
item.ref_match(ref_mode, original_path.syntax().text_range().start());
|
||||
}
|
||||
} else {
|
||||
// completion requested on an empty identifier, there is no path here yet.
|
||||
|
|
|
|||
|
|
@ -25,10 +25,10 @@ fn render(ctx: RenderContext<'_>, const_: hir::Const) -> Option<CompletionItem>
|
|||
.detail(detail)
|
||||
.set_relevance(ctx.completion_relevance());
|
||||
|
||||
if let Some(actm) = const_.as_assoc_item(db) {
|
||||
if let Some(trt) = actm.container_or_implemented_trait(db) {
|
||||
item.trait_name(trt.name(db).display_no_db(ctx.completion.edition).to_smolstr());
|
||||
}
|
||||
if let Some(actm) = const_.as_assoc_item(db)
|
||||
&& let Some(trt) = actm.container_or_implemented_trait(db)
|
||||
{
|
||||
item.trait_name(trt.name(db).display_no_db(ctx.completion.edition).to_smolstr());
|
||||
}
|
||||
item.insert_text(escaped_name);
|
||||
|
||||
|
|
|
|||
|
|
@ -132,10 +132,10 @@ fn render(
|
|||
super::path_ref_match(completion, path_ctx, &ret_type, &mut item);
|
||||
}
|
||||
FuncKind::Method(DotAccess { receiver: Some(receiver), .. }, _) => {
|
||||
if let Some(original_expr) = completion.sema.original_ast_node(receiver.clone()) {
|
||||
if let Some(ref_mode) = compute_ref_match(completion, &ret_type) {
|
||||
item.ref_match(ref_mode, original_expr.syntax().text_range().start());
|
||||
}
|
||||
if let Some(original_expr) = completion.sema.original_ast_node(receiver.clone())
|
||||
&& let Some(ref_mode) = compute_ref_match(completion, &ret_type)
|
||||
{
|
||||
item.ref_match(ref_mode, original_expr.syntax().text_range().start());
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
|
|
@ -169,12 +169,10 @@ fn render(
|
|||
item.add_import(import_to_add);
|
||||
}
|
||||
None => {
|
||||
if let Some(actm) = assoc_item {
|
||||
if let Some(trt) = actm.container_or_implemented_trait(db) {
|
||||
item.trait_name(
|
||||
trt.name(db).display_no_db(ctx.completion.edition).to_smolstr(),
|
||||
);
|
||||
}
|
||||
if let Some(actm) = assoc_item
|
||||
&& let Some(trt) = actm.container_or_implemented_trait(db)
|
||||
{
|
||||
item.trait_name(trt.name(db).display_no_db(ctx.completion.edition).to_smolstr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -378,15 +376,13 @@ fn params<'db>(
|
|||
ctx.config.callable.as_ref()?;
|
||||
|
||||
// Don't add parentheses if the expected type is a function reference with the same signature.
|
||||
if let Some(expected) = ctx.expected_type.as_ref().filter(|e| e.is_fn()) {
|
||||
if let Some(expected) = expected.as_callable(ctx.db) {
|
||||
if let Some(completed) = func.ty(ctx.db).as_callable(ctx.db) {
|
||||
if expected.sig() == completed.sig() {
|
||||
cov_mark::hit!(no_call_parens_if_fn_ptr_needed);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(expected) = ctx.expected_type.as_ref().filter(|e| e.is_fn())
|
||||
&& let Some(expected) = expected.as_callable(ctx.db)
|
||||
&& let Some(completed) = func.ty(ctx.db).as_callable(ctx.db)
|
||||
&& expected.sig() == completed.sig()
|
||||
{
|
||||
cov_mark::hit!(no_call_parens_if_fn_ptr_needed);
|
||||
return None;
|
||||
}
|
||||
|
||||
let self_param = if has_dot_receiver || matches!(func_kind, FuncKind::Method(_, Some(_))) {
|
||||
|
|
|
|||
|
|
@ -51,10 +51,10 @@ fn render(
|
|||
.detail(detail)
|
||||
.set_relevance(ctx.completion_relevance());
|
||||
|
||||
if let Some(actm) = type_alias.as_assoc_item(db) {
|
||||
if let Some(trt) = actm.container_or_implemented_trait(db) {
|
||||
item.trait_name(trt.name(db).display_no_db(ctx.completion.edition).to_smolstr());
|
||||
}
|
||||
if let Some(actm) = type_alias.as_assoc_item(db)
|
||||
&& let Some(trt) = actm.container_or_implemented_trait(db)
|
||||
{
|
||||
item.trait_name(trt.name(db).display_no_db(ctx.completion.edition).to_smolstr());
|
||||
}
|
||||
item.insert_text(escaped_name);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue