implement completion render for callable fields

This commit is contained in:
dfireBird 2023-11-12 14:49:31 +05:30
parent a0e690a7e9
commit 7cf3ab4bd2
No known key found for this signature in database
GPG Key ID: 26D522CA5FC2B93D

View File

@ -21,7 +21,7 @@
use text_edit::TextEdit; use text_edit::TextEdit;
use crate::{ use crate::{
context::{DotAccess, PathCompletionCtx, PathKind, PatternContext}, context::{DotAccess, DotAccessKind, PathCompletionCtx, PathKind, PatternContext},
item::{Builder, CompletionRelevanceTypeMatch}, item::{Builder, CompletionRelevanceTypeMatch},
render::{ render::{
function::render_fn, function::render_fn,
@ -150,17 +150,34 @@ pub(crate) fn render_field(
.lookup_by(name); .lookup_by(name);
if ty.is_fn() || ty.is_closure() { if ty.is_fn() || ty.is_closure() {
let mut builder = TextEdit::builder(); let mut builder = TextEdit::builder();
// Use TextEdit to insert / replace the ranges: // Using TextEdit, insert '(' before the struct name and ')' before the
// 1. Insert one character ('(') before start of struct name // dot access, then comes the field name and optionally insert function
// 2. Insert one character (')') before call parens // call parens.
// 3. Variable character of the actual field name
// 4. Optionally, two character ('()') for fn call if let Some(receiver) = &dot_access.receiver {
// let range = receiver.syntax().text_range();
// TODO: Find a way to get the above ranges, especially the first two builder.insert(range.start(), "(".to_string());
builder.insert(range.end(), ")".to_string());
}
builder.replace( builder.replace(
ctx.source_range(), ctx.source_range(),
field_with_receiver(db, receiver.as_ref(), &escaped_name).into(), field_with_receiver(db, receiver.as_ref(), &escaped_name).into(),
); );
let is_fn_expected =
ctx.completion.expected_type.as_ref().map_or(false, |ty| ty.is_fn() || ty.is_closure());
// This could be refactored as method of DotAccessKind
let is_parens_needed = if let DotAccessKind::Method { has_parens } = dot_access.kind {
!has_parens
} else {
true
};
if !is_fn_expected && is_parens_needed {
builder.insert(ctx.source_range().end(), "()".to_string());
}
item.text_edit(builder.finish()); item.text_edit(builder.finish());
} else { } else {
item.insert_text(field_with_receiver(db, receiver.as_ref(), &escaped_name)); item.insert_text(field_with_receiver(db, receiver.as_ref(), &escaped_name));