about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/ide-completion/src/completions/dot.rs63
-rw-r--r--crates/ide-completion/src/render.rs4
2 files changed, 22 insertions, 45 deletions
diff --git a/crates/ide-completion/src/completions/dot.rs b/crates/ide-completion/src/completions/dot.rs
index 2f0b6988f21..e427be381bb 100644
--- a/crates/ide-completion/src/completions/dot.rs
+++ b/crates/ide-completion/src/completions/dot.rs
@@ -26,23 +26,19 @@ pub(crate) fn complete_dot(
         item.add_to(acc, ctx.db);
     }
 
+    let is_field_access = matches!(dot_access.kind, DotAccessKind::Field { .. });
+
+    complete_fields(
+        acc,
+        ctx,
+        receiver_ty,
+        |acc, field, ty| acc.add_field(ctx, dot_access, None, field, &ty),
+        |acc, field, ty| acc.add_tuple_field(ctx, None, field, &ty),
+        is_field_access,
+    );
+
     if let DotAccessKind::Method { .. } = dot_access.kind {
         cov_mark::hit!(test_no_struct_field_completion_for_method_call);
-        complete_fn_fields(
-            acc,
-            ctx,
-            receiver_ty,
-            |acc, field, ty| acc.add_field(ctx, dot_access, None, field, &ty),
-            |acc, field, ty| acc.add_tuple_field(ctx, None, field, &ty),
-        );
-    } else {
-        complete_fields(
-            acc,
-            ctx,
-            receiver_ty,
-            |acc, field, ty| acc.add_field(ctx, dot_access, None, field, &ty),
-            |acc, field, ty| acc.add_tuple_field(ctx, None, field, &ty),
-        );
     }
     complete_methods(ctx, receiver_ty, |func| acc.add_method(ctx, dot_access, func, None, None));
 }
@@ -89,6 +85,7 @@ pub(crate) fn complete_undotted_self(
             )
         },
         |acc, field, ty| acc.add_tuple_field(ctx, Some(hir::known::SELF_PARAM), field, &ty),
+        true,
     );
     complete_methods(ctx, &ty, |func| {
         acc.add_method(
@@ -111,18 +108,23 @@ fn complete_fields(
     receiver: &hir::Type,
     mut named_field: impl FnMut(&mut Completions, hir::Field, hir::Type),
     mut tuple_index: impl FnMut(&mut Completions, usize, hir::Type),
+    is_field_access: bool,
 ) {
     let mut seen_names = FxHashSet::default();
     for receiver in receiver.autoderef(ctx.db) {
         for (field, ty) in receiver.fields(ctx.db) {
-            if seen_names.insert(field.name(ctx.db)) {
+            if seen_names.insert(field.name(ctx.db))
+                && (is_field_access || ty.is_fn() || ty.is_closure())
+            {
                 named_field(acc, field, ty);
             }
         }
         for (i, ty) in receiver.tuple_fields(ctx.db).into_iter().enumerate() {
             // Tuples are always the last type in a deref chain, so just check if the name is
             // already seen without inserting into the hashset.
-            if !seen_names.contains(&hir::Name::new_tuple_field(i)) {
+            if !seen_names.contains(&hir::Name::new_tuple_field(i))
+                && (is_field_access || ty.is_fn() || ty.is_closure())
+            {
                 // Tuple fields are always public (tuple struct fields are handled above).
                 tuple_index(acc, i, ty);
             }
@@ -151,33 +153,6 @@ fn complete_methods(
     );
 }
 
-fn complete_fn_fields(
-    acc: &mut Completions,
-    ctx: &CompletionContext<'_>,
-    receiver: &hir::Type,
-    mut named_field: impl FnMut(&mut Completions, hir::Field, hir::Type),
-    mut tuple_index: impl FnMut(&mut Completions, usize, hir::Type),
-) {
-    let mut seen_names = FxHashSet::default();
-    for receiver in receiver.autoderef(ctx.db) {
-        for (field, ty) in receiver.fields(ctx.db) {
-            if seen_names.insert(field.name(ctx.db)) && (ty.is_fn() || ty.is_closure()) {
-                named_field(acc, field, ty);
-            }
-        }
-        for (i, ty) in receiver.tuple_fields(ctx.db).into_iter().enumerate() {
-            // Tuples are always the last type in a deref chain, so just check if the name is
-            // already seen without inserting into the hashset.
-            if !seen_names.contains(&hir::Name::new_tuple_field(i))
-                && (ty.is_fn() || ty.is_closure())
-            {
-                // Tuple fields are always public (tuple struct fields are handled above).
-                tuple_index(acc, i, ty);
-            }
-        }
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use expect_test::{expect, Expect};
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index f733f36f5d6..453ff061bce 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -148,7 +148,9 @@ pub(crate) fn render_field(
         .set_documentation(field.docs(db))
         .set_deprecated(is_deprecated)
         .lookup_by(name);
-    if ty.is_fn() || ty.is_closure() {
+
+    let is_field_access = matches!(dot_access.kind, DotAccessKind::Field { .. });
+    if !is_field_access || ty.is_fn() || ty.is_closure() {
         let mut builder = TextEdit::builder();
         // Using TextEdit, insert '(' before the struct name and ')' before the
         // dot access, then comes the field name and optionally insert function