Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide_completion/src/render/builder_ext.rs')
-rw-r--r--crates/ide_completion/src/render/builder_ext.rs58
1 files changed, 53 insertions, 5 deletions
diff --git a/crates/ide_completion/src/render/builder_ext.rs b/crates/ide_completion/src/render/builder_ext.rs
index 33d3a5ee18..ea8222f76a 100644
--- a/crates/ide_completion/src/render/builder_ext.rs
+++ b/crates/ide_completion/src/render/builder_ext.rs
@@ -1,12 +1,14 @@
//! Extensions for `Builder` structure required for item rendering.
+use either::Either;
use itertools::Itertools;
+use syntax::ast::{self, HasName};
use crate::{context::CallKind, item::Builder, patterns::ImmediateLocation, CompletionContext};
#[derive(Debug)]
pub(super) enum Params {
- Named(Vec<String>),
+ Named(Vec<(Either<ast::SelfParam, ast::Param>, hir::Param)>),
Anonymous(usize),
}
@@ -76,10 +78,46 @@ impl Builder {
self.trigger_call_info();
let snippet = match (ctx.config.add_call_argument_snippets, params) {
(true, Params::Named(params)) => {
- let function_params_snippet =
- params.iter().enumerate().format_with(", ", |(index, param_name), f| {
- f(&format_args!("${{{}:{}}}", index + 1, param_name))
- });
+ let function_params_snippet = params.iter().enumerate().format_with(
+ ", ",
+ |(index, (param_source, param)), f| {
+ let name;
+ let text;
+ let (ref_, name) = match param_source {
+ Either::Left(self_param) => (
+ match self_param.kind() {
+ ast::SelfParamKind::Owned => "",
+ ast::SelfParamKind::Ref => "&",
+ ast::SelfParamKind::MutRef => "&mut ",
+ },
+ "self",
+ ),
+ Either::Right(it) => {
+ let n = (|| {
+ let mut pat = it.pat()?;
+ loop {
+ match pat {
+ ast::Pat::IdentPat(pat) => break pat.name(),
+ ast::Pat::RefPat(it) => pat = it.pat()?,
+ _ => return None,
+ }
+ }
+ })();
+ match n {
+ Some(n) => {
+ name = n;
+ text = name.text();
+ let text = text.as_str().trim_start_matches('_');
+ let ref_ = ref_of_param(ctx, text, param.ty());
+ (ref_, text)
+ }
+ None => ("", "_"),
+ }
+ }
+ };
+ f(&format_args!("${{{}:{}{}}}", index + 1, ref_, name))
+ },
+ );
format!("{}({})$0", name, function_params_snippet)
}
_ => {
@@ -93,3 +131,13 @@ impl Builder {
self.lookup_by(name).label(label).insert_snippet(cap, snippet)
}
}
+fn ref_of_param(ctx: &CompletionContext, arg: &str, ty: &hir::Type) -> &'static str {
+ if let Some(derefed_ty) = ty.remove_ref() {
+ for (name, local) in ctx.locals.iter() {
+ if name.as_text().as_deref() == Some(arg) && local.ty(ctx.db) == derefed_ty {
+ return if ty.is_mutable_reference() { "&mut " } else { "&" };
+ }
+ }
+ }
+ ""
+}