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.rs3
-rw-r--r--crates/ra_ide/src/completion/complete_dot.rs145
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs8
-rw-r--r--crates/ra_ide/src/completion/completion_item.rs50
-rw-r--r--crates/ra_ide/src/completion/presentation.rs2
-rw-r--r--crates/ra_ide/src/completion/test_utils.rs11
-rw-r--r--crates/ra_ide/src/display/function_signature.rs70
-rw-r--r--crates/ra_ide/src/lib.rs15
8 files changed, 274 insertions, 30 deletions
diff --git a/crates/ra_ide/src/completion.rs b/crates/ra_ide/src/completion.rs
index 4a1a2a04a..3be8b1903 100644
--- a/crates/ra_ide/src/completion.rs
+++ b/crates/ra_ide/src/completion.rs
@@ -94,5 +94,8 @@ pub(crate) fn completions(
94 complete_macro_in_item_position::complete_macro_in_item_position(&mut acc, &ctx); 94 complete_macro_in_item_position::complete_macro_in_item_position(&mut acc, &ctx);
95 complete_trait_impl::complete_trait_impl(&mut acc, &ctx); 95 complete_trait_impl::complete_trait_impl(&mut acc, &ctx);
96 96
97 // Reorder completion items if there is a sort_option
98 acc.sort();
99
97 Some(acc) 100 Some(acc)
98} 101}
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs
index f433faef3..cb899d8ff 100644
--- a/crates/ra_ide/src/completion/complete_dot.rs
+++ b/crates/ra_ide/src/completion/complete_dot.rs
@@ -1,13 +1,23 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir::{HasVisibility, Type}; 3use hir::{
4 HasVisibility,
5 // HirDisplay,
6 Type,
7};
4 8
5use crate::completion::completion_item::CompletionKind; 9use crate::completion::completion_item::CompletionKind;
6use crate::{ 10use crate::{
7 completion::{completion_context::CompletionContext, completion_item::Completions}, 11 call_info::call_info,
12 completion::{
13 completion_context::CompletionContext,
14 completion_item::{Completions, SortOption},
15 },
16 // CallInfo,
8 CompletionItem, 17 CompletionItem,
9}; 18};
10use rustc_hash::FxHashSet; 19use rustc_hash::FxHashSet;
20// use std::cmp::Ordering;
11 21
12/// Complete dot accesses, i.e. fields or methods (and .await syntax). 22/// Complete dot accesses, i.e. fields or methods (and .await syntax).
13pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { 23pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
@@ -37,7 +47,41 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
37 47
38fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) { 48fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) {
39 for receiver in receiver.autoderef(ctx.db) { 49 for receiver in receiver.autoderef(ctx.db) {
40 for (field, ty) in receiver.fields(ctx.db) { 50 let fields = receiver.fields(ctx.db);
51
52 // If we use this implementation we can delete call_info in the CompletionContext
53 if let Some(call_info) = call_info(ctx.db, ctx.file_position) {
54 acc.with_sort_option(SortOption::CallFn(call_info));
55 }
56
57 // // For Call Fn
58 // if let Some(call_info) = &ctx.call_info {
59 // if let Some(active_parameter_type) = call_info.active_parameter_type() {
60 // let active_parameter_name = call_info.active_parameter_name().unwrap();
61 // fields.sort_by(|a, b| {
62 // // For the same type
63 // if active_parameter_type == a.1.display(ctx.db).to_string() {
64 // // If same type + same name then go top position
65 // if active_parameter_name == a.0.name(ctx.db).to_string() {
66 // Ordering::Less
67 // } else {
68 // if active_parameter_type == b.1.display(ctx.db).to_string() {
69 // Ordering::Equal
70 // } else {
71 // Ordering::Less
72 // }
73 // }
74 // } else {
75 // Ordering::Greater
76 // }
77 // });
78 // }
79 // }
80
81 // For Lit struct fields
82 // ---
83
84 for (field, ty) in fields {
41 if ctx.scope().module().map_or(false, |m| !field.is_visible_from(ctx.db, m)) { 85 if ctx.scope().module().map_or(false, |m| !field.is_visible_from(ctx.db, m)) {
42 // Skip private field. FIXME: If the definition location of the 86 // Skip private field. FIXME: If the definition location of the
43 // field is editable, we should show the completion 87 // field is editable, we should show the completion
@@ -70,13 +114,20 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &T
70 114
71#[cfg(test)] 115#[cfg(test)]
72mod tests { 116mod tests {
73 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; 117 use crate::completion::{
118 test_utils::{do_completion, do_completion_without_sort},
119 CompletionItem, CompletionKind,
120 };
74 use insta::assert_debug_snapshot; 121 use insta::assert_debug_snapshot;
75 122
76 fn do_ref_completion(code: &str) -> Vec<CompletionItem> { 123 fn do_ref_completion(code: &str) -> Vec<CompletionItem> {
77 do_completion(code, CompletionKind::Reference) 124 do_completion(code, CompletionKind::Reference)
78 } 125 }
79 126
127 fn do_ref_completion_without_sort(code: &str) -> Vec<CompletionItem> {
128 do_completion_without_sort(code, CompletionKind::Reference)
129 }
130
80 #[test] 131 #[test]
81 fn test_struct_field_completion() { 132 fn test_struct_field_completion() {
82 assert_debug_snapshot!( 133 assert_debug_snapshot!(
@@ -104,6 +155,92 @@ mod tests {
104 } 155 }
105 156
106 #[test] 157 #[test]
158 fn test_struct_field_completion_in_func_call() {
159 assert_debug_snapshot!(
160 do_ref_completion_without_sort(
161 r"
162 struct A { another_field: i64, the_field: u32, my_string: String }
163 fn test(my_param: u32) -> u32 { my_param }
164 fn foo(a: A) {
165 test(a.<|>)
166 }
167 ",
168 ),
169 @r###"
170 [
171 CompletionItem {
172 label: "the_field",
173 source_range: [201; 201),
174 delete: [201; 201),
175 insert: "the_field",
176 kind: Field,
177 detail: "u32",
178 },
179 CompletionItem {
180 label: "another_field",
181 source_range: [201; 201),
182 delete: [201; 201),
183 insert: "another_field",
184 kind: Field,
185 detail: "i64",
186 },
187 CompletionItem {
188 label: "my_string",
189 source_range: [201; 201),
190 delete: [201; 201),
191 insert: "my_string",
192 kind: Field,
193 detail: "{unknown}",
194 },
195 ]
196 "###
197 );
198 }
199
200 #[test]
201 fn test_struct_field_completion_in_func_call_with_type_and_name() {
202 assert_debug_snapshot!(
203 do_ref_completion_without_sort(
204 r"
205 struct A { another_field: i64, another_good_type: u32, the_field: u32 }
206 fn test(the_field: u32) -> u32 { the_field }
207 fn foo(a: A) {
208 test(a.<|>)
209 }
210 ",
211 ),
212 @r###"
213 [
214 CompletionItem {
215 label: "the_field",
216 source_range: [208; 208),
217 delete: [208; 208),
218 insert: "the_field",
219 kind: Field,
220 detail: "u32",
221 },
222 CompletionItem {
223 label: "another_good_type",
224 source_range: [208; 208),
225 delete: [208; 208),
226 insert: "another_good_type",
227 kind: Field,
228 detail: "u32",
229 },
230 CompletionItem {
231 label: "another_field",
232 source_range: [208; 208),
233 delete: [208; 208),
234 insert: "another_field",
235 kind: Field,
236 detail: "i64",
237 },
238 ]
239 "###
240 );
241 }
242
243 #[test]
107 fn test_struct_field_completion_self() { 244 fn test_struct_field_completion_self() {
108 assert_debug_snapshot!( 245 assert_debug_snapshot!(
109 do_ref_completion( 246 do_ref_completion(
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs
index 8b3401595..da054f7a2 100644
--- a/crates/ra_ide/src/completion/completion_context.rs
+++ b/crates/ra_ide/src/completion/completion_context.rs
@@ -11,7 +11,7 @@ use ra_syntax::{
11}; 11};
12use ra_text_edit::AtomTextEdit; 12use ra_text_edit::AtomTextEdit;
13 13
14use crate::{completion::CompletionConfig, FilePosition}; 14use crate::{call_info::call_info, completion::CompletionConfig, CallInfo, FilePosition};
15 15
16/// `CompletionContext` is created early during completion to figure out, where 16/// `CompletionContext` is created early during completion to figure out, where
17/// exactly is the cursor, syntax-wise. 17/// exactly is the cursor, syntax-wise.
@@ -21,6 +21,7 @@ pub(crate) struct CompletionContext<'a> {
21 pub(super) db: &'a RootDatabase, 21 pub(super) db: &'a RootDatabase,
22 pub(super) config: &'a CompletionConfig, 22 pub(super) config: &'a CompletionConfig,
23 pub(super) offset: TextUnit, 23 pub(super) offset: TextUnit,
24 pub(super) file_position: FilePosition,
24 /// The token before the cursor, in the original file. 25 /// The token before the cursor, in the original file.
25 pub(super) original_token: SyntaxToken, 26 pub(super) original_token: SyntaxToken,
26 /// The token before the cursor, in the macro-expanded file. 27 /// The token before the cursor, in the macro-expanded file.
@@ -32,6 +33,7 @@ pub(crate) struct CompletionContext<'a> {
32 pub(super) record_lit_syntax: Option<ast::RecordLit>, 33 pub(super) record_lit_syntax: Option<ast::RecordLit>,
33 pub(super) record_pat_syntax: Option<ast::RecordPat>, 34 pub(super) record_pat_syntax: Option<ast::RecordPat>,
34 pub(super) impl_def: Option<ast::ImplDef>, 35 pub(super) impl_def: Option<ast::ImplDef>,
36 pub(super) call_info: Option<CallInfo>,
35 pub(super) is_param: bool, 37 pub(super) is_param: bool,
36 /// If a name-binding or reference to a const in a pattern. 38 /// If a name-binding or reference to a const in a pattern.
37 /// Irrefutable patterns (like let) are excluded. 39 /// Irrefutable patterns (like let) are excluded.
@@ -88,9 +90,11 @@ impl<'a> CompletionContext<'a> {
88 original_token, 90 original_token,
89 token, 91 token,
90 offset: position.offset, 92 offset: position.offset,
93 file_position: position,
91 krate, 94 krate,
92 name_ref_syntax: None, 95 name_ref_syntax: None,
93 function_syntax: None, 96 function_syntax: None,
97 call_info: None,
94 use_item_syntax: None, 98 use_item_syntax: None,
95 record_lit_syntax: None, 99 record_lit_syntax: None,
96 record_pat_syntax: None, 100 record_pat_syntax: None,
@@ -262,6 +266,8 @@ impl<'a> CompletionContext<'a> {
262 self.use_item_syntax = 266 self.use_item_syntax =
263 self.sema.ancestors_with_macros(self.token.parent()).find_map(ast::UseItem::cast); 267 self.sema.ancestors_with_macros(self.token.parent()).find_map(ast::UseItem::cast);
264 268
269 self.call_info = call_info(self.db, self.file_position);
270
265 self.function_syntax = self 271 self.function_syntax = self
266 .sema 272 .sema
267 .ancestors_with_macros(self.token.parent()) 273 .ancestors_with_macros(self.token.parent())
diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs
index bc0f1aff5..f8e6e53f1 100644
--- a/crates/ra_ide/src/completion/completion_item.rs
+++ b/crates/ra_ide/src/completion/completion_item.rs
@@ -1,7 +1,8 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use std::fmt; 3use std::{cmp::Ordering, fmt};
4 4
5use crate::CallInfo;
5use hir::Documentation; 6use hir::Documentation;
6use ra_syntax::TextRange; 7use ra_syntax::TextRange;
7use ra_text_edit::TextEdit; 8use ra_text_edit::TextEdit;
@@ -297,10 +298,17 @@ impl<'a> Into<CompletionItem> for Builder {
297 } 298 }
298} 299}
299 300
301#[derive(Debug)]
302pub(crate) enum SortOption {
303 CallFn(CallInfo),
304 // LitStruct,
305}
306
300/// Represents an in-progress set of completions being built. 307/// Represents an in-progress set of completions being built.
301#[derive(Debug, Default)] 308#[derive(Debug, Default)]
302pub(crate) struct Completions { 309pub(crate) struct Completions {
303 buf: Vec<CompletionItem>, 310 buf: Vec<CompletionItem>,
311 sort_option: Option<SortOption>,
304} 312}
305 313
306impl Completions { 314impl Completions {
@@ -314,6 +322,46 @@ impl Completions {
314 { 322 {
315 items.into_iter().for_each(|item| self.add(item.into())) 323 items.into_iter().for_each(|item| self.add(item.into()))
316 } 324 }
325
326 pub(crate) fn with_sort_option(&mut self, sort_option: SortOption) {
327 self.sort_option = Some(sort_option);
328 }
329
330 pub(crate) fn sort(&mut self) {
331 if self.sort_option.is_none() {
332 return;
333 }
334 let sort_option = self.sort_option.as_ref().unwrap();
335
336 match sort_option {
337 SortOption::CallFn(call_info) => {
338 if let Some(active_parameter_type) = call_info.active_parameter_type() {
339 let active_parameter_name = call_info.active_parameter_name().unwrap();
340
341 self.buf.sort_by(|a, b| {
342 // For the same type
343 if let Some(a_parameter_type) = &a.detail {
344 if &active_parameter_type == a_parameter_type {
345 // If same type + same name then go top position
346 if active_parameter_name != a.label {
347 if let Some(b_parameter_type) = &b.detail {
348 if &active_parameter_type == b_parameter_type {
349 return Ordering::Equal;
350 }
351 }
352 }
353 Ordering::Less
354 } else {
355 Ordering::Greater
356 }
357 } else {
358 Ordering::Greater
359 }
360 });
361 }
362 } // _ => unimplemented!("sort options not already implemented"),
363 }
364 }
317} 365}
318 366
319impl Into<Vec<CompletionItem>> for Completions { 367impl Into<Vec<CompletionItem>> for Completions {
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index 55f75b15a..8be2d02d0 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -367,7 +367,7 @@ mod tests {
367 ra_fixture: &str, 367 ra_fixture: &str,
368 options: CompletionConfig, 368 options: CompletionConfig,
369 ) -> Vec<CompletionItem> { 369 ) -> Vec<CompletionItem> {
370 do_completion_with_options(ra_fixture, CompletionKind::Reference, &options) 370 do_completion_with_options(ra_fixture, CompletionKind::Reference, &options, true)
371 } 371 }
372 372
373 #[test] 373 #[test]
diff --git a/crates/ra_ide/src/completion/test_utils.rs b/crates/ra_ide/src/completion/test_utils.rs
index eb90b5279..f54d15a90 100644
--- a/crates/ra_ide/src/completion/test_utils.rs
+++ b/crates/ra_ide/src/completion/test_utils.rs
@@ -7,13 +7,18 @@ use crate::{
7}; 7};
8 8
9pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { 9pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> {
10 do_completion_with_options(code, kind, &CompletionConfig::default()) 10 do_completion_with_options(code, kind, &CompletionConfig::default(), true)
11}
12
13pub(crate) fn do_completion_without_sort(code: &str, kind: CompletionKind) -> Vec<CompletionItem> {
14 do_completion_with_options(code, kind, &CompletionConfig::default(), false)
11} 15}
12 16
13pub(crate) fn do_completion_with_options( 17pub(crate) fn do_completion_with_options(
14 code: &str, 18 code: &str,
15 kind: CompletionKind, 19 kind: CompletionKind,
16 options: &CompletionConfig, 20 options: &CompletionConfig,
21 sort_by_key: bool,
17) -> Vec<CompletionItem> { 22) -> Vec<CompletionItem> {
18 let (analysis, position) = if code.contains("//-") { 23 let (analysis, position) = if code.contains("//-") {
19 analysis_and_position(code) 24 analysis_and_position(code)
@@ -24,6 +29,8 @@ pub(crate) fn do_completion_with_options(
24 let completion_items: Vec<CompletionItem> = completions.into(); 29 let completion_items: Vec<CompletionItem> = completions.into();
25 let mut kind_completions: Vec<CompletionItem> = 30 let mut kind_completions: Vec<CompletionItem> =
26 completion_items.into_iter().filter(|c| c.completion_kind == kind).collect(); 31 completion_items.into_iter().filter(|c| c.completion_kind == kind).collect();
27 kind_completions.sort_by_key(|c| c.label().to_owned()); 32 if sort_by_key {
33 kind_completions.sort_by_key(|c| c.label().to_owned());
34 }
28 kind_completions 35 kind_completions
29} 36}
diff --git a/crates/ra_ide/src/display/function_signature.rs b/crates/ra_ide/src/display/function_signature.rs
index b967a6816..2d175882b 100644
--- a/crates/ra_ide/src/display/function_signature.rs
+++ b/crates/ra_ide/src/display/function_signature.rs
@@ -36,6 +36,8 @@ pub struct FunctionSignature {
36 pub parameters: Vec<String>, 36 pub parameters: Vec<String>,
37 /// Parameter names of the function 37 /// Parameter names of the function
38 pub parameter_names: Vec<String>, 38 pub parameter_names: Vec<String>,
39 /// Parameter types of the function
40 pub parameter_types: Vec<String>,
39 /// Optional return type 41 /// Optional return type
40 pub ret_type: Option<String>, 42 pub ret_type: Option<String>,
41 /// Where predicates 43 /// Where predicates
@@ -62,14 +64,20 @@ impl FunctionSignature {
62 return None; 64 return None;
63 }; 65 };
64 66
65 let params = st 67 let mut params = vec![];
66 .fields(db) 68 let mut parameter_types = vec![];
67 .into_iter() 69 for field in st.fields(db).into_iter() {
68 .map(|field: hir::StructField| { 70 let ty = field.signature_ty(db);
69 let ty = field.signature_ty(db); 71 let raw_param = format!("{}", ty.display(db));
70 format!("{}", ty.display(db)) 72
71 }) 73 if let Some(param_type) = raw_param.split(':').nth(1) {
72 .collect(); 74 parameter_types.push(param_type[1..].to_string());
75 } else {
76 // The unwrap_or_else is useful when you have tuple struct
77 parameter_types.push(raw_param.clone());
78 }
79 params.push(raw_param);
80 }
73 81
74 Some( 82 Some(
75 FunctionSignature { 83 FunctionSignature {
@@ -79,6 +87,7 @@ impl FunctionSignature {
79 ret_type: node.name().map(|n| n.text().to_string()), 87 ret_type: node.name().map(|n| n.text().to_string()),
80 parameters: params, 88 parameters: params,
81 parameter_names: vec![], 89 parameter_names: vec![],
90 parameter_types,
82 generic_parameters: generic_parameters(&node), 91 generic_parameters: generic_parameters(&node),
83 where_predicates: where_predicates(&node), 92 where_predicates: where_predicates(&node),
84 doc: None, 93 doc: None,
@@ -99,15 +108,21 @@ impl FunctionSignature {
99 108
100 let name = format!("{}::{}", parent_name, variant.name(db)); 109 let name = format!("{}::{}", parent_name, variant.name(db));
101 110
102 let params = variant 111 let mut params = vec![];
103 .fields(db) 112 let mut parameter_types = vec![];
104 .into_iter() 113 for field in variant.fields(db).into_iter() {
105 .map(|field: hir::StructField| { 114 let ty = field.signature_ty(db);
106 let name = field.name(db); 115 let raw_param = format!("{}", ty.display(db));
107 let ty = field.signature_ty(db); 116 if let Some(param_type) = raw_param.split(':').nth(1) {
108 format!("{}: {}", name, ty.display(db)) 117 parameter_types.push(param_type[1..].to_string());
109 }) 118 } else {
110 .collect(); 119 // The unwrap_or_else is useful when you have tuple
120 parameter_types.push(raw_param);
121 }
122 let name = field.name(db);
123
124 params.push(format!("{}: {}", name, ty.display(db)));
125 }
111 126
112 Some( 127 Some(
113 FunctionSignature { 128 FunctionSignature {
@@ -117,6 +132,7 @@ impl FunctionSignature {
117 ret_type: None, 132 ret_type: None,
118 parameters: params, 133 parameters: params,
119 parameter_names: vec![], 134 parameter_names: vec![],
135 parameter_types,
120 generic_parameters: vec![], 136 generic_parameters: vec![],
121 where_predicates: vec![], 137 where_predicates: vec![],
122 doc: None, 138 doc: None,
@@ -139,6 +155,7 @@ impl FunctionSignature {
139 ret_type: None, 155 ret_type: None,
140 parameters: params, 156 parameters: params,
141 parameter_names: vec![], 157 parameter_names: vec![],
158 parameter_types: vec![],
142 generic_parameters: vec![], 159 generic_parameters: vec![],
143 where_predicates: vec![], 160 where_predicates: vec![],
144 doc: None, 161 doc: None,
@@ -151,18 +168,28 @@ impl FunctionSignature {
151 168
152impl From<&'_ ast::FnDef> for FunctionSignature { 169impl From<&'_ ast::FnDef> for FunctionSignature {
153 fn from(node: &ast::FnDef) -> FunctionSignature { 170 fn from(node: &ast::FnDef) -> FunctionSignature {
154 fn param_list(node: &ast::FnDef) -> (bool, Vec<String>) { 171 fn param_list(node: &ast::FnDef) -> (bool, Vec<String>, Vec<String>) {
155 let mut res = vec![]; 172 let mut res = vec![];
173 let mut res_types = vec![];
156 let mut has_self_param = false; 174 let mut has_self_param = false;
157 if let Some(param_list) = node.param_list() { 175 if let Some(param_list) = node.param_list() {
158 if let Some(self_param) = param_list.self_param() { 176 if let Some(self_param) = param_list.self_param() {
159 has_self_param = true; 177 has_self_param = true;
160 res.push(self_param.syntax().text().to_string()) 178 let raw_param = self_param.syntax().text().to_string();
179
180 // FIXME: better solution ?
181 res_types.push(
182 raw_param.split(':').nth(1).unwrap_or_else(|| " Self")[1..].to_string(),
183 );
184 res.push(raw_param);
161 } 185 }
162 186
163 res.extend(param_list.params().map(|param| param.syntax().text().to_string())); 187 res.extend(param_list.params().map(|param| param.syntax().text().to_string()));
188 res_types.extend(param_list.params().map(|param| {
189 param.syntax().text().to_string().split(':').nth(1).unwrap()[1..].to_string()
190 }));
164 } 191 }
165 (has_self_param, res) 192 (has_self_param, res, res_types)
166 } 193 }
167 194
168 fn param_name_list(node: &ast::FnDef) -> Vec<String> { 195 fn param_name_list(node: &ast::FnDef) -> Vec<String> {
@@ -192,7 +219,7 @@ impl From<&'_ ast::FnDef> for FunctionSignature {
192 res 219 res
193 } 220 }
194 221
195 let (has_self_param, parameters) = param_list(node); 222 let (has_self_param, parameters, parameter_types) = param_list(node);
196 223
197 FunctionSignature { 224 FunctionSignature {
198 kind: CallableKind::Function, 225 kind: CallableKind::Function,
@@ -204,6 +231,7 @@ impl From<&'_ ast::FnDef> for FunctionSignature {
204 .map(|n| n.syntax().text().to_string()), 231 .map(|n| n.syntax().text().to_string()),
205 parameters, 232 parameters,
206 parameter_names: param_name_list(node), 233 parameter_names: param_name_list(node),
234 parameter_types,
207 generic_parameters: generic_parameters(node), 235 generic_parameters: generic_parameters(node),
208 where_predicates: where_predicates(node), 236 where_predicates: where_predicates(node),
209 // docs are processed separately 237 // docs are processed separately
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs
index 5599f143f..357c01cdf 100644
--- a/crates/ra_ide/src/lib.rs
+++ b/crates/ra_ide/src/lib.rs
@@ -127,6 +127,21 @@ pub struct CallInfo {
127 pub active_parameter: Option<usize>, 127 pub active_parameter: Option<usize>,
128} 128}
129 129
130impl CallInfo {
131 pub fn active_parameter_type(&self) -> Option<String> {
132 if let Some(id) = self.active_parameter {
133 return self.signature.parameter_types.get(id).map(|param_ty| param_ty.clone());
134 }
135 None
136 }
137 pub fn active_parameter_name(&self) -> Option<String> {
138 if let Some(id) = self.active_parameter {
139 return self.signature.parameter_names.get(id).map(|param_ty| param_ty.clone());
140 }
141 None
142 }
143}
144
130/// `AnalysisHost` stores the current state of the world. 145/// `AnalysisHost` stores the current state of the world.
131#[derive(Debug)] 146#[derive(Debug)]
132pub struct AnalysisHost { 147pub struct AnalysisHost {