diff --git a/crates/ide-completion/src/completions/field.rs b/crates/ide-completion/src/completions/field.rs index b4f7e1839dee..08e4f087507f 100644 --- a/crates/ide-completion/src/completions/field.rs +++ b/crates/ide-completion/src/completions/field.rs @@ -1,7 +1,9 @@ //! Completion of field list position. +use syntax::{AstNode, ast}; + use crate::{ - CompletionContext, Completions, + CompletionContext, CompletionItem, CompletionItemKind, Completions, context::{PathCompletionCtx, Qualified}, }; @@ -10,6 +12,8 @@ pub(crate) fn complete_field_list_tuple_variant( ctx: &CompletionContext<'_, '_>, path_ctx: &PathCompletionCtx<'_>, ) { + complete_record_fields(acc, ctx); + if ctx.qualifier_ctx.vis_node.is_some() { } else if let PathCompletionCtx { has_macro_bang: false, @@ -30,6 +34,8 @@ pub(crate) fn complete_field_list_record_variant( acc: &mut Completions, ctx: &CompletionContext<'_, '_>, ) { + complete_record_fields(acc, ctx); + if ctx.qualifier_ctx.vis_node.is_none() { let mut add_keyword = |kw, snippet| acc.add_keyword_snippet(ctx, kw, snippet); add_keyword("pub(crate)", "pub(crate) $0"); @@ -37,3 +43,28 @@ pub(crate) fn complete_field_list_record_variant( add_keyword("pub", "pub $0"); } } + +fn complete_record_fields(acc: &mut Completions, ctx: &CompletionContext<'_, '_>) { + let Some(record_field) = ctx + .original_token + .parent_ancestors() + .nth(1) + .and_then(ast::RecordField::cast) + .filter(|it| it.ty().is_none() && it.default_val().is_none()) + else { + return; + }; + let Some(stmt_list) = record_field.syntax().ancestors().find_map(ast::StmtList::cast) else { + return; + }; + super::fn_param::locals_from_stmt_list_scope(ctx, stmt_list, |name, ty| { + let text = syntax::format_smolstr!("{}: {ty},", name.display(ctx.db, ctx.edition)); + CompletionItem::new( + CompletionItemKind::Binding, + record_field.syntax().text_range(), + text, + ctx.edition, + ) + .add_to(acc, ctx.db); + }); +} diff --git a/crates/ide-completion/src/completions/fn_param.rs b/crates/ide-completion/src/completions/fn_param.rs index f1e8e5f39eaa..4846ecc7e409 100644 --- a/crates/ide-completion/src/completions/fn_param.rs +++ b/crates/ide-completion/src/completions/fn_param.rs @@ -64,7 +64,7 @@ pub(crate) fn complete_fn_param( ParamKind::Closure(closure) => { if is_simple_param(param) { let stmt_list = closure.syntax().ancestors().find_map(ast::StmtList::cast)?; - params_from_stmt_list_scope(ctx, stmt_list, |name, ty| { + locals_from_stmt_list_scope(ctx, stmt_list, |name, ty| { add_new_item_to_acc(&format_smolstr!( "{}: {ty}", name.display(ctx.db, ctx.edition) @@ -123,7 +123,7 @@ fn fill_fn_params( if let Some(stmt_list) = function.syntax().parent().and_then(ast::StmtList::cast) && is_simple_param(current_param) { - params_from_stmt_list_scope(ctx, stmt_list, |name, ty| { + locals_from_stmt_list_scope(ctx, stmt_list, |name, ty| { file_params .entry(format_smolstr!("{}: {ty}", name.display(ctx.db, ctx.edition))) .or_insert(name.display(ctx.db, ctx.edition).to_smolstr()); @@ -138,7 +138,7 @@ fn fill_fn_params( file_params.keys().for_each(|whole_param| add_new_item_to_acc(whole_param)); } -fn params_from_stmt_list_scope( +pub(crate) fn locals_from_stmt_list_scope( ctx: &CompletionContext<'_, '_>, stmt_list: ast::StmtList, mut cb: impl FnMut(hir::Name, String), diff --git a/crates/ide-completion/src/tests/record.rs b/crates/ide-completion/src/tests/record.rs index ddb929446900..d49b1b43489f 100644 --- a/crates/ide-completion/src/tests/record.rs +++ b/crates/ide-completion/src/tests/record.rs @@ -398,3 +398,58 @@ pub(super) struct S { "#, ); } + +#[test] +fn local_record_shows_locals_for_record_def_fields() { + check( + r#" +fn outer() { + let foo = 3; + { + let bar = 3; + struct Foo { + b$0 + } + let baz = 3; + let qux = 3; + } + let fez = 3; +} +"#, + expect![[r#" + bn bar: i32, + bn baz: i32, + bn foo: i32, + kw pub + kw pub(crate) + kw pub(super) + "#]], + ); + + check( + r#" +fn outer() { + let foo = 3; + { + let bar = 3; + enum Foo { + Variant { + b$0 + } + } + let baz = 3; + let qux = 3; + } + let fez = 3; +} +"#, + expect![[r#" + bn bar: i32, + bn baz: i32, + bn foo: i32, + kw pub + kw pub(crate) + kw pub(super) + "#]], + ); +}