mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 05:15:04 +00:00
internal: Store function param names in ItemTree
This commit is contained in:
parent
f609efff87
commit
cd9d76e0ca
11 changed files with 60 additions and 91 deletions
|
@ -1,13 +1,12 @@
|
|||
//! Extensions for `Builder` structure required for item rendering.
|
||||
|
||||
use itertools::Itertools;
|
||||
use syntax::ast::{self, HasName};
|
||||
|
||||
use crate::{context::PathKind, item::Builder, patterns::ImmediateLocation, CompletionContext};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) enum Params {
|
||||
Named(Option<ast::SelfParam>, Vec<(ast::Param, hir::Param)>),
|
||||
Named(Option<hir::SelfParam>, Vec<hir::Param>),
|
||||
Anonymous(usize),
|
||||
}
|
||||
|
||||
|
@ -80,44 +79,22 @@ impl Builder {
|
|||
let offset = if self_param.is_some() { 2 } else { 1 };
|
||||
let function_params_snippet = params.iter().enumerate().format_with(
|
||||
", ",
|
||||
|(index, (param_source, param)), f| {
|
||||
let name;
|
||||
let text;
|
||||
let n = (|| {
|
||||
let mut pat = param_source.pat()?;
|
||||
loop {
|
||||
match pat {
|
||||
ast::Pat::IdentPat(pat) => break pat.name(),
|
||||
ast::Pat::RefPat(it) => pat = it.pat()?,
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
})();
|
||||
let (ref_, name) = 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 + offset, ref_, name))
|
||||
|(index, param), f| match param.name(ctx.db) {
|
||||
Some(n) => {
|
||||
let smol_str = n.to_smol_str();
|
||||
let text = smol_str.as_str().trim_start_matches('_');
|
||||
let ref_ = ref_of_param(ctx, text, param.ty());
|
||||
f(&format_args!("${{{}:{}{}}}", index + offset, ref_, text))
|
||||
}
|
||||
None => f(&format_args!("${{{}:_}}", index + offset,)),
|
||||
},
|
||||
);
|
||||
match self_param {
|
||||
Some(self_param) => {
|
||||
let prefix = match self_param.kind() {
|
||||
ast::SelfParamKind::Owned => "",
|
||||
ast::SelfParamKind::Ref => "&",
|
||||
ast::SelfParamKind::MutRef => "&mut ",
|
||||
};
|
||||
format!(
|
||||
"{}(${{1:{}self}}{}{})$0",
|
||||
"{}(${{1:{}}}{}{})$0",
|
||||
name,
|
||||
prefix,
|
||||
self_param.display(ctx.db),
|
||||
if params.is_empty() { "" } else { ", " },
|
||||
function_params_snippet
|
||||
)
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
//! Renderer for function calls.
|
||||
|
||||
use hir::{AsAssocItem, HasSource, HirDisplay};
|
||||
use hir::{AsAssocItem, HirDisplay};
|
||||
use ide_db::SymbolKind;
|
||||
use itertools::Itertools;
|
||||
use stdx::format_to;
|
||||
use syntax::ast;
|
||||
|
||||
use crate::{
|
||||
item::{CompletionItem, CompletionItemKind, CompletionRelevance, ImportEdit},
|
||||
|
@ -41,21 +40,6 @@ struct FunctionRender<'a> {
|
|||
name: hir::Name,
|
||||
receiver: Option<hir::Name>,
|
||||
func: hir::Function,
|
||||
/// NB: having `ast::Fn` here might or might not be a good idea. The problem
|
||||
/// with it is that, to get an `ast::`, you want to parse the corresponding
|
||||
/// source file. So, when flyimport completions suggest a bunch of
|
||||
/// functions, we spend quite some time parsing many files.
|
||||
///
|
||||
/// We need ast because we want to access parameter names (patterns). We can
|
||||
/// add them to the hir of the function itself, but parameter names are not
|
||||
/// something hir cares otherwise.
|
||||
///
|
||||
/// Alternatively we can reconstruct params from the function body, but that
|
||||
/// would require parsing anyway.
|
||||
///
|
||||
/// It seems that just using `ast` is the best choice -- most of parses
|
||||
/// should be cached anyway.
|
||||
param_list: Option<ast::ParamList>,
|
||||
is_method: bool,
|
||||
}
|
||||
|
||||
|
@ -68,9 +52,8 @@ impl<'a> FunctionRender<'a> {
|
|||
is_method: bool,
|
||||
) -> Option<FunctionRender<'a>> {
|
||||
let name = local_name.unwrap_or_else(|| fn_.name(ctx.db()));
|
||||
let param_list = fn_.source(ctx.db())?.value.param_list();
|
||||
|
||||
Some(FunctionRender { ctx, name, receiver, func: fn_, param_list, is_method })
|
||||
Some(FunctionRender { ctx, name, receiver, func: fn_, is_method })
|
||||
}
|
||||
|
||||
fn render(self, import_to_add: Option<ImportEdit>) -> CompletionItem {
|
||||
|
@ -151,23 +134,18 @@ impl<'a> FunctionRender<'a> {
|
|||
}
|
||||
|
||||
fn params(&self) -> Params {
|
||||
let ast_params = match &self.param_list {
|
||||
Some(it) => it,
|
||||
None => return Params::Named(None, Vec::new()),
|
||||
};
|
||||
let params = ast_params.params();
|
||||
let (params, self_param) =
|
||||
if self.ctx.completion.has_dot_receiver() || self.receiver.is_some() {
|
||||
(self.func.method_params(self.ctx.db()).unwrap_or_default(), None)
|
||||
} else {
|
||||
let self_param = self.func.self_param(self.ctx.db());
|
||||
|
||||
let (params, self_param) = if self.ctx.completion.has_dot_receiver()
|
||||
|| self.receiver.is_some()
|
||||
{
|
||||
(params.zip(self.func.method_params(self.ctx.db()).unwrap_or_default()).collect(), None)
|
||||
} else {
|
||||
let mut assoc_params = self.func.assoc_fn_params(self.ctx.db());
|
||||
if self.func.self_param(self.ctx.db()).is_some() {
|
||||
assoc_params.remove(0);
|
||||
}
|
||||
(params.zip(assoc_params).collect(), ast_params.self_param())
|
||||
};
|
||||
let mut assoc_params = self.func.assoc_fn_params(self.ctx.db());
|
||||
if self_param.is_some() {
|
||||
assoc_params.remove(0);
|
||||
}
|
||||
(assoc_params, self_param)
|
||||
};
|
||||
|
||||
Params::Named(self_param, params)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue