aboutsummaryrefslogtreecommitdiff
path: root/crates/completion/src/render/function.rs
diff options
context:
space:
mode:
authorIgor Aleksanov <[email protected]>2020-11-01 09:35:04 +0000
committerIgor Aleksanov <[email protected]>2020-11-03 07:16:35 +0000
commitfc8a1cd8006b021541ff673ec7f37a0f4b7bef57 (patch)
treeb5153e990c97a86608ad69b4aacc2b2dd88f1614 /crates/completion/src/render/function.rs
parent245e1b533b5be5ea4a917957fb02d7f57e6b4661 (diff)
Introduce render module
Diffstat (limited to 'crates/completion/src/render/function.rs')
-rw-r--r--crates/completion/src/render/function.rs87
1 files changed, 87 insertions, 0 deletions
diff --git a/crates/completion/src/render/function.rs b/crates/completion/src/render/function.rs
new file mode 100644
index 000000000..16f15e22c
--- /dev/null
+++ b/crates/completion/src/render/function.rs
@@ -0,0 +1,87 @@
1use hir::{Documentation, HasAttrs, HasSource, Type};
2use syntax::{ast::Fn, display::function_declaration};
3
4use crate::{
5 item::{CompletionItem, CompletionItemKind, CompletionKind},
6 render::{builder_ext::Params, RenderContext},
7};
8
9#[derive(Debug)]
10pub(crate) struct FunctionRender<'a> {
11 ctx: RenderContext<'a>,
12 name: String,
13 fn_: hir::Function,
14 ast_node: Fn,
15}
16
17impl<'a> FunctionRender<'a> {
18 pub(crate) fn new(
19 ctx: RenderContext<'a>,
20 local_name: Option<String>,
21 fn_: hir::Function,
22 ) -> FunctionRender<'a> {
23 let name = local_name.unwrap_or_else(|| fn_.name(ctx.db()).to_string());
24 let ast_node = fn_.source(ctx.db()).value;
25
26 FunctionRender { ctx, name, fn_, ast_node }
27 }
28
29 pub(crate) fn render(self) -> CompletionItem {
30 let params = self.params();
31 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), self.name.clone())
32 .kind(self.kind())
33 .set_documentation(self.docs())
34 .set_deprecated(self.ctx.is_deprecated(self.fn_))
35 .detail(self.detail())
36 .add_call_parens(self.ctx.completion, self.name, params)
37 .build()
38 }
39
40 fn detail(&self) -> String {
41 function_declaration(&self.ast_node)
42 }
43
44 fn add_arg(&self, arg: &str, ty: &Type) -> String {
45 if let Some(derefed_ty) = ty.remove_ref() {
46 for (name, local) in self.ctx.completion.locals.iter() {
47 if name == arg && local.ty(self.ctx.db()) == derefed_ty {
48 return (if ty.is_mutable_reference() { "&mut " } else { "&" }).to_string()
49 + &arg.to_string();
50 }
51 }
52 }
53 arg.to_string()
54 }
55
56 fn params(&self) -> Params {
57 let params_ty = self.fn_.params(self.ctx.db());
58 let params = self
59 .ast_node
60 .param_list()
61 .into_iter()
62 .flat_map(|it| it.params())
63 .zip(params_ty)
64 .flat_map(|(it, param_ty)| {
65 if let Some(pat) = it.pat() {
66 let name = pat.to_string();
67 let arg = name.trim_start_matches("mut ").trim_start_matches('_');
68 return Some(self.add_arg(arg, param_ty.ty()));
69 }
70 None
71 })
72 .collect();
73 Params::Named(params)
74 }
75
76 fn kind(&self) -> CompletionItemKind {
77 if self.fn_.self_param(self.ctx.db()).is_some() {
78 CompletionItemKind::Method
79 } else {
80 CompletionItemKind::Function
81 }
82 }
83
84 fn docs(&self) -> Option<Documentation> {
85 self.fn_.docs(self.ctx.db())
86 }
87}