aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide')
-rw-r--r--crates/ra_ide/src/completion/presentation.rs17
-rw-r--r--crates/ra_ide/src/display.rs18
-rw-r--r--crates/ra_ide/src/display/function_signature.rs152
3 files changed, 7 insertions, 180 deletions
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index 6aab93e17..c7b74e635 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -11,10 +11,7 @@ use crate::{
11 completion_item::Builder, CompletionContext, CompletionItem, CompletionItemKind, 11 completion_item::Builder, CompletionContext, CompletionItem, CompletionItemKind,
12 CompletionKind, Completions, 12 CompletionKind, Completions,
13 }, 13 },
14 display::{ 14 display::{const_label, function_declaration, macro_label, type_label},
15 const_label, function_declaration, function_signature::FunctionSignature, macro_label,
16 type_label,
17 },
18 CompletionScore, RootDatabase, 15 CompletionScore, RootDatabase,
19}; 16};
20 17
@@ -198,7 +195,6 @@ impl Completions {
198 195
199 let name = local_name.unwrap_or_else(|| func.name(ctx.db).to_string()); 196 let name = local_name.unwrap_or_else(|| func.name(ctx.db).to_string());
200 let ast_node = func.source(ctx.db).value; 197 let ast_node = func.source(ctx.db).value;
201 let function_signature = FunctionSignature::from(&ast_node);
202 198
203 let mut builder = 199 let mut builder =
204 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone()) 200 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone())
@@ -211,11 +207,12 @@ impl Completions {
211 .set_deprecated(is_deprecated(func, ctx.db)) 207 .set_deprecated(is_deprecated(func, ctx.db))
212 .detail(function_declaration(&ast_node)); 208 .detail(function_declaration(&ast_node));
213 209
214 let params = function_signature 210 let params = ast_node
215 .parameter_names 211 .param_list()
216 .iter() 212 .into_iter()
217 .skip(if function_signature.has_self_param { 1 } else { 0 }) 213 .flat_map(|it| it.params())
218 .map(|name| name.trim_start_matches('_').into()) 214 .flat_map(|it| it.pat())
215 .map(|pat| pat.to_string().trim_start_matches('_').into())
219 .collect(); 216 .collect();
220 217
221 builder = builder.add_call_parens(ctx, name, Params::Named(params)); 218 builder = builder.add_call_parens(ctx, name, Params::Named(params));
diff --git a/crates/ra_ide/src/display.rs b/crates/ra_ide/src/display.rs
index 34ce32e81..6d4151dd8 100644
--- a/crates/ra_ide/src/display.rs
+++ b/crates/ra_ide/src/display.rs
@@ -1,7 +1,6 @@
1//! This module contains utilities for turning SyntaxNodes and HIR types 1//! This module contains utilities for turning SyntaxNodes and HIR types
2//! into types that may be used to render in a UI. 2//! into types that may be used to render in a UI.
3 3
4pub(crate) mod function_signature;
5mod navigation_target; 4mod navigation_target;
6mod short_label; 5mod short_label;
7 6
@@ -77,23 +76,6 @@ pub(crate) fn type_label(node: &ast::TypeAliasDef) -> String {
77 label.trim().to_owned() 76 label.trim().to_owned()
78} 77}
79 78
80pub(crate) fn generic_parameters<N: TypeParamsOwner>(node: &N) -> Vec<String> {
81 let mut res = vec![];
82 if let Some(type_params) = node.type_param_list() {
83 res.extend(type_params.lifetime_params().map(|p| p.syntax().text().to_string()));
84 res.extend(type_params.type_params().map(|p| p.syntax().text().to_string()));
85 }
86 res
87}
88
89pub(crate) fn where_predicates<N: TypeParamsOwner>(node: &N) -> Vec<String> {
90 let mut res = vec![];
91 if let Some(clause) = node.where_clause() {
92 res.extend(clause.predicates().map(|p| p.syntax().text().to_string()));
93 }
94 res
95}
96
97pub(crate) fn macro_label(node: &ast::MacroCall) -> String { 79pub(crate) fn macro_label(node: &ast::MacroCall) -> String {
98 let name = node.name().map(|name| name.syntax().text().to_string()).unwrap_or_default(); 80 let name = node.name().map(|name| name.syntax().text().to_string()).unwrap_or_default();
99 let vis = if node.has_atom_attr("macro_export") { "#[macro_export]\n" } else { "" }; 81 let vis = if node.has_atom_attr("macro_export") { "#[macro_export]\n" } else { "" };
diff --git a/crates/ra_ide/src/display/function_signature.rs b/crates/ra_ide/src/display/function_signature.rs
deleted file mode 100644
index f6e11357f..000000000
--- a/crates/ra_ide/src/display/function_signature.rs
+++ /dev/null
@@ -1,152 +0,0 @@
1//! FIXME: write short doc here
2
3// FIXME: this modules relies on strings and AST way too much, and it should be
4// rewritten (matklad 2020-05-07)
5use std::convert::From;
6
7use hir::Documentation;
8use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner};
9use stdx::split_delim;
10
11use crate::display::{generic_parameters, where_predicates};
12
13#[derive(Debug)]
14pub(crate) enum CallableKind {
15 Function,
16}
17
18/// Contains information about a function signature
19#[derive(Debug)]
20pub(crate) struct FunctionSignature {
21 pub(crate) kind: CallableKind,
22 /// Optional visibility
23 pub(crate) visibility: Option<String>,
24 /// Qualifiers like `async`, `unsafe`, ...
25 pub(crate) qualifier: FunctionQualifier,
26 /// Name of the function
27 pub(crate) name: Option<String>,
28 /// Documentation for the function
29 pub(crate) doc: Option<Documentation>,
30 /// Generic parameters
31 pub(crate) generic_parameters: Vec<String>,
32 /// Parameters of the function
33 pub(crate) parameters: Vec<String>,
34 /// Parameter names of the function
35 pub(crate) parameter_names: Vec<String>,
36 /// Parameter types of the function
37 pub(crate) parameter_types: Vec<String>,
38 /// Optional return type
39 pub(crate) ret_type: Option<String>,
40 /// Where predicates
41 pub(crate) where_predicates: Vec<String>,
42 /// Self param presence
43 pub(crate) has_self_param: bool,
44}
45
46#[derive(Debug, Default)]
47pub(crate) struct FunctionQualifier {
48 // `async` and `const` are mutually exclusive. Do we need to enforcing it here?
49 pub(crate) is_async: bool,
50 pub(crate) is_const: bool,
51 pub(crate) is_unsafe: bool,
52 /// The string `extern ".."`
53 pub(crate) extern_abi: Option<String>,
54}
55
56impl From<&'_ ast::FnDef> for FunctionSignature {
57 fn from(node: &ast::FnDef) -> FunctionSignature {
58 fn param_list(node: &ast::FnDef) -> (bool, Vec<String>, Vec<String>) {
59 let mut res = vec![];
60 let mut res_types = vec![];
61 let mut has_self_param = false;
62 if let Some(param_list) = node.param_list() {
63 if let Some(self_param) = param_list.self_param() {
64 has_self_param = true;
65 let raw_param = self_param.syntax().text().to_string();
66
67 res_types.push(
68 raw_param
69 .split(':')
70 .nth(1)
71 .and_then(|it| it.get(1..))
72 .unwrap_or_else(|| "Self")
73 .to_string(),
74 );
75 res.push(raw_param);
76 }
77
78 // macro-generated functions are missing whitespace
79 fn fmt_param(param: ast::Param) -> String {
80 let text = param.syntax().text().to_string();
81 match split_delim(&text, ':') {
82 Some((left, right)) => format!("{}: {}", left.trim(), right.trim()),
83 _ => text,
84 }
85 }
86
87 res.extend(param_list.params().map(fmt_param));
88 res_types.extend(param_list.params().map(|param| {
89 let param_text = param.syntax().text().to_string();
90 match param_text.split(':').nth(1).and_then(|it| it.get(1..)) {
91 Some(it) => it.to_string(),
92 None => param_text,
93 }
94 }));
95 }
96 (has_self_param, res, res_types)
97 }
98
99 fn param_name_list(node: &ast::FnDef) -> Vec<String> {
100 let mut res = vec![];
101 if let Some(param_list) = node.param_list() {
102 if let Some(self_param) = param_list.self_param() {
103 res.push(self_param.syntax().text().to_string())
104 }
105
106 res.extend(
107 param_list
108 .params()
109 .map(|param| {
110 Some(
111 param
112 .pat()?
113 .syntax()
114 .descendants()
115 .find_map(ast::Name::cast)?
116 .text()
117 .to_string(),
118 )
119 })
120 .map(|param| param.unwrap_or_default()),
121 );
122 }
123 res
124 }
125
126 let (has_self_param, parameters, parameter_types) = param_list(node);
127
128 FunctionSignature {
129 kind: CallableKind::Function,
130 visibility: node.visibility().map(|n| n.syntax().text().to_string()),
131 qualifier: FunctionQualifier {
132 is_async: node.async_token().is_some(),
133 is_const: node.const_token().is_some(),
134 is_unsafe: node.unsafe_token().is_some(),
135 extern_abi: node.abi().map(|n| n.to_string()),
136 },
137 name: node.name().map(|n| n.text().to_string()),
138 ret_type: node
139 .ret_type()
140 .and_then(|r| r.type_ref())
141 .map(|n| n.syntax().text().to_string()),
142 parameters,
143 parameter_names: param_name_list(node),
144 parameter_types,
145 generic_parameters: generic_parameters(node),
146 where_predicates: where_predicates(node),
147 // docs are processed separately
148 doc: None,
149 has_self_param,
150 }
151 }
152}