refactor complete_fn_fields function and correct branch checks

This commit is contained in:
dfireBird 2023-11-22 18:33:38 +05:30
parent 8296b16f38
commit 5c0c8ceaf7
No known key found for this signature in database
GPG key ID: 26D522CA5FC2B93D
2 changed files with 22 additions and 45 deletions

View file

@ -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};

View file

@ -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