Unnamed repository; edit this file 'description' to name the repository.
refactor `complete_fn_fields` function and correct branch checks
dfireBird 2023-11-28
parent 8296b16 · commit 5c0c8ce
-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 2f0b6988f2..e427be381b 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 f733f36f5d..453ff061bc 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