diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs index 750b0222593..147563ef103 100644 --- a/crates/ide-completion/src/completions.rs +++ b/crates/ide-completion/src/completions.rs @@ -379,6 +379,7 @@ impl Completions { pub(crate) fn add_field( &mut self, ctx: &CompletionContext, + dot_access: &DotAccess, receiver: Option, field: hir::Field, ty: &hir::Type, @@ -390,6 +391,7 @@ impl Completions { }; let item = render_field( RenderContext::new(ctx).private_editable(is_private_editable), + dot_access, receiver, field, ty, diff --git a/crates/ide-completion/src/completions/dot.rs b/crates/ide-completion/src/completions/dot.rs index b58a9f39f2e..bf0bce2198c 100644 --- a/crates/ide-completion/src/completions/dot.rs +++ b/crates/ide-completion/src/completions/dot.rs @@ -29,7 +29,7 @@ pub(crate) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext, dot_a acc, ctx, &receiver_ty, - |acc, field, ty| acc.add_field(ctx, None, field, &ty), + |acc, field, ty| acc.add_field(ctx, dot_access, None, field, &ty), |acc, field, ty| acc.add_tuple_field(ctx, None, field, &ty), ); } @@ -64,7 +64,19 @@ pub(crate) fn complete_undotted_self( acc, ctx, &ty, - |acc, field, ty| acc.add_field(ctx, Some(hir::known::SELF_PARAM), field, &ty), + |acc, field, ty| { + acc.add_field( + ctx, + &DotAccess { + receiver: None, + receiver_ty: None, + kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }, + }, + Some(hir::known::SELF_PARAM), + field, + &ty, + ) + }, |acc, field, ty| acc.add_tuple_field(ctx, Some(hir::known::SELF_PARAM), field, &ty), ); complete_methods(ctx, &ty, |func| { diff --git a/crates/ide-completion/src/completions/record.rs b/crates/ide-completion/src/completions/record.rs index 9f834e1ca15..8cef3a70182 100644 --- a/crates/ide-completion/src/completions/record.rs +++ b/crates/ide-completion/src/completions/record.rs @@ -3,7 +3,7 @@ use ide_db::SymbolKind; use syntax::ast::{self, Expr}; use crate::{ - context::{ExprCtx, PathCompletionCtx, PatternContext, Qualified}, + context::{DotAccess, DotAccessKind, ExprCtx, PathCompletionCtx, PatternContext, Qualified}, CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevancePostfixMatch, Completions, }; @@ -107,7 +107,17 @@ fn complete_fields( missing_fields: Vec<(hir::Field, hir::Type)>, ) { for (field, ty) in missing_fields { - acc.add_field(ctx, None, field, &ty); + acc.add_field( + ctx, + &DotAccess { + receiver: None, + receiver_ty: None, + kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }, + }, + None, + field, + &ty, + ); } } diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs index c29a50dd632..6571e673527 100644 --- a/crates/ide-completion/src/render.rs +++ b/crates/ide-completion/src/render.rs @@ -17,7 +17,7 @@ use ide_db::{ use syntax::{AstNode, SmolStr, SyntaxKind, TextRange}; use crate::{ - context::{PathCompletionCtx, PathKind, PatternContext}, + context::{DotAccess, PathCompletionCtx, PathKind, PatternContext}, item::{Builder, CompletionRelevanceTypeMatch}, render::{ function::render_fn, @@ -110,6 +110,7 @@ impl<'a> RenderContext<'a> { pub(crate) fn render_field( ctx: RenderContext<'_>, + dot_access: &DotAccess, receiver: Option, field: hir::Field, ty: &hir::Type, @@ -134,10 +135,10 @@ pub(crate) fn render_field( if is_keyword && !matches!(name.as_str(), "self" | "crate" | "super" | "Self") { item.insert_text(format!("r#{}", name)); } - if let Some(_ref_match) = compute_ref_match(ctx.completion, ty) { - // FIXME - // For now we don't properly calculate the edits for ref match - // completions on struct fields, so we've disabled them. See #8058. + if let Some(receiver) = &dot_access.receiver { + if let Some(ref_match) = compute_ref_match(ctx.completion, ty) { + item.ref_match(ref_match, receiver.syntax().text_range().start()); + } } item.build() } @@ -1535,9 +1536,6 @@ impl Foo { fn baz(&self) -> u32 { 0 } } fn foo(f: Foo) { let _: &u32 = f.b$0 } "#, &[CompletionItemKind::Method, CompletionItemKind::SymbolKind(SymbolKind::Field)], - // FIXME - // Ideally we'd also suggest &f.bar as exact - // type matches. See #8058. expect![[r#" [ CompletionItem { @@ -1559,6 +1557,7 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 } Field, ), detail: "u32", + ref_match: "&@96", }, ] "#]],