aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--xtask/tests/tidy-tests/main.rs6
9 files changed, 277 insertions, 33 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 {
diff --git a/xtask/tests/tidy-tests/main.rs b/xtask/tests/tidy-tests/main.rs
index 4f525fcd0..b3d6ddac9 100644
--- a/xtask/tests/tidy-tests/main.rs
+++ b/xtask/tests/tidy-tests/main.rs
@@ -34,7 +34,7 @@ fn check_todo(path: &Path, text: &str) {
34 } 34 }
35 if text.contains("TODO") || text.contains("TOOD") || text.contains("todo!") { 35 if text.contains("TODO") || text.contains("TOOD") || text.contains("todo!") {
36 panic!( 36 panic!(
37 "\nTODO markers should not be committed to the master branch,\n\ 37 "\nTODO markers or todo! macros should not be committed to the master branch,\n\
38 use FIXME instead\n\ 38 use FIXME instead\n\
39 {}\n", 39 {}\n",
40 path.display(), 40 path.display(),
@@ -46,9 +46,9 @@ fn check_trailing_ws(path: &Path, text: &str) {
46 if is_exclude_dir(path, &["test_data"]) { 46 if is_exclude_dir(path, &["test_data"]) {
47 return; 47 return;
48 } 48 }
49 for line in text.lines() { 49 for (line_number, line) in text.lines().enumerate() {
50 if line.chars().last().map(char::is_whitespace) == Some(true) { 50 if line.chars().last().map(char::is_whitespace) == Some(true) {
51 panic!("Trailing whitespace in {}", path.display()) 51 panic!("Trailing whitespace in {} at line {}", path.display(), line_number)
52 } 52 }
53 } 53 }
54} 54}