diff options
Diffstat (limited to 'crates/ra_ide')
-rw-r--r-- | crates/ra_ide/src/call_hierarchy.rs | 10 | ||||
-rw-r--r-- | crates/ra_ide/src/call_info.rs | 332 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/presentation.rs | 7 | ||||
-rw-r--r-- | crates/ra_ide/src/display/function_signature.rs | 21 | ||||
-rw-r--r-- | crates/ra_ide/src/inlay_hints.rs | 10 |
5 files changed, 177 insertions, 203 deletions
diff --git a/crates/ra_ide/src/call_hierarchy.rs b/crates/ra_ide/src/call_hierarchy.rs index cb7e62cd6..6af251d23 100644 --- a/crates/ra_ide/src/call_hierarchy.rs +++ b/crates/ra_ide/src/call_hierarchy.rs | |||
@@ -95,9 +95,9 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio | |||
95 | if let Some(func_target) = match &call_node { | 95 | if let Some(func_target) = match &call_node { |
96 | FnCallNode::CallExpr(expr) => { | 96 | FnCallNode::CallExpr(expr) => { |
97 | //FIXME: Type::as_callable is broken | 97 | //FIXME: Type::as_callable is broken |
98 | let callable_def = sema.type_of_expr(&expr.expr()?)?.as_callable()?; | 98 | let callable = sema.type_of_expr(&expr.expr()?)?.as_callable(db)?; |
99 | match callable_def { | 99 | match callable.kind() { |
100 | hir::CallableDefId::FunctionId(it) => { | 100 | hir::CallableKind::Function(it) => { |
101 | let fn_def: hir::Function = it.into(); | 101 | let fn_def: hir::Function = it.into(); |
102 | let nav = fn_def.to_nav(db); | 102 | let nav = fn_def.to_nav(db); |
103 | Some(nav) | 103 | Some(nav) |
@@ -109,10 +109,6 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio | |||
109 | let function = sema.resolve_method_call(&expr)?; | 109 | let function = sema.resolve_method_call(&expr)?; |
110 | Some(function.to_nav(db)) | 110 | Some(function.to_nav(db)) |
111 | } | 111 | } |
112 | FnCallNode::MacroCallExpr(macro_call) => { | ||
113 | let macro_def = sema.resolve_macro_call(¯o_call)?; | ||
114 | Some(macro_def.to_nav(db)) | ||
115 | } | ||
116 | } { | 112 | } { |
117 | Some((func_target, name_ref.syntax().text_range())) | 113 | Some((func_target, name_ref.syntax().text_range())) |
118 | } else { | 114 | } else { |
diff --git a/crates/ra_ide/src/call_info.rs b/crates/ra_ide/src/call_info.rs index 1fe1c21de..a2d23b2ec 100644 --- a/crates/ra_ide/src/call_info.rs +++ b/crates/ra_ide/src/call_info.rs | |||
@@ -1,20 +1,41 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | use hir::Semantics; | 2 | use hir::{Docs, HirDisplay, Semantics, Type}; |
3 | use ra_ide_db::RootDatabase; | 3 | use ra_ide_db::RootDatabase; |
4 | use ra_syntax::{ | 4 | use ra_syntax::{ |
5 | ast::{self, ArgListOwner}, | 5 | ast::{self, ArgListOwner}, |
6 | match_ast, AstNode, SyntaxNode, SyntaxToken, | 6 | match_ast, AstNode, SyntaxNode, SyntaxToken, TextRange, TextSize, |
7 | }; | 7 | }; |
8 | use stdx::format_to; | ||
8 | use test_utils::mark; | 9 | use test_utils::mark; |
9 | 10 | ||
10 | use crate::{FilePosition, FunctionSignature}; | 11 | use crate::FilePosition; |
11 | 12 | ||
12 | /// Contains information about a call site. Specifically the | 13 | /// Contains information about a call site. Specifically the |
13 | /// `FunctionSignature`and current parameter. | 14 | /// `FunctionSignature`and current parameter. |
14 | #[derive(Debug)] | 15 | #[derive(Debug)] |
15 | pub struct CallInfo { | 16 | pub struct CallInfo { |
16 | pub signature: FunctionSignature, | 17 | pub doc: Option<String>, |
18 | pub signature: String, | ||
17 | pub active_parameter: Option<usize>, | 19 | pub active_parameter: Option<usize>, |
20 | parameters: Vec<TextRange>, | ||
21 | } | ||
22 | |||
23 | impl CallInfo { | ||
24 | pub fn parameter_labels(&self) -> impl Iterator<Item = &str> + '_ { | ||
25 | self.parameters.iter().map(move |&it| &self.signature[it]) | ||
26 | } | ||
27 | pub fn parameter_ranges(&self) -> &[TextRange] { | ||
28 | &self.parameters | ||
29 | } | ||
30 | fn push_param(&mut self, param: &str) { | ||
31 | if !self.signature.ends_with('(') { | ||
32 | self.signature.push_str(", "); | ||
33 | } | ||
34 | let start = TextSize::of(&self.signature); | ||
35 | self.signature.push_str(param); | ||
36 | let end = TextSize::of(&self.signature); | ||
37 | self.parameters.push(TextRange::new(start, end)) | ||
38 | } | ||
18 | } | 39 | } |
19 | 40 | ||
20 | /// Computes parameter information for the given call expression. | 41 | /// Computes parameter information for the given call expression. |
@@ -24,105 +45,127 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal | |||
24 | let file = file.syntax(); | 45 | let file = file.syntax(); |
25 | let token = file.token_at_offset(position.offset).next()?; | 46 | let token = file.token_at_offset(position.offset).next()?; |
26 | let token = sema.descend_into_macros(token); | 47 | let token = sema.descend_into_macros(token); |
27 | call_info_for_token(&sema, token) | ||
28 | } | ||
29 | 48 | ||
30 | #[derive(Debug)] | 49 | let (callable, active_parameter) = call_info_impl(&sema, token)?; |
31 | pub(crate) struct ActiveParameter { | ||
32 | /// FIXME: should be `Type` and `Name | ||
33 | pub(crate) ty: String, | ||
34 | pub(crate) name: String, | ||
35 | } | ||
36 | 50 | ||
37 | impl ActiveParameter { | 51 | let mut res = |
38 | pub(crate) fn at(db: &RootDatabase, position: FilePosition) -> Option<Self> { | 52 | CallInfo { doc: None, signature: String::new(), parameters: vec![], active_parameter }; |
39 | call_info(db, position)?.into_active_parameter() | 53 | |
54 | match callable.kind() { | ||
55 | hir::CallableKind::Function(func) => { | ||
56 | res.doc = func.docs(db).map(|it| it.as_str().to_string()); | ||
57 | format_to!(res.signature, "fn {}", func.name(db)); | ||
58 | } | ||
59 | hir::CallableKind::TupleStruct(strukt) => { | ||
60 | res.doc = strukt.docs(db).map(|it| it.as_str().to_string()); | ||
61 | format_to!(res.signature, "struct {}", strukt.name(db)); | ||
62 | } | ||
63 | hir::CallableKind::TupleEnumVariant(variant) => { | ||
64 | res.doc = variant.docs(db).map(|it| it.as_str().to_string()); | ||
65 | format_to!( | ||
66 | res.signature, | ||
67 | "enum {}::{}", | ||
68 | variant.parent_enum(db).name(db), | ||
69 | variant.name(db) | ||
70 | ); | ||
71 | } | ||
40 | } | 72 | } |
41 | 73 | ||
42 | pub(crate) fn at_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Option<Self> { | 74 | res.signature.push('('); |
43 | call_info_for_token(sema, token)?.into_active_parameter() | 75 | { |
76 | if let Some(self_param) = callable.receiver_param(db) { | ||
77 | format_to!(res.signature, "{}", self_param) | ||
78 | } | ||
79 | let mut buf = String::new(); | ||
80 | for (pat, ty) in callable.params(db) { | ||
81 | buf.clear(); | ||
82 | if let Some(pat) = pat { | ||
83 | format_to!(buf, "{}: ", pat); | ||
84 | } | ||
85 | format_to!(buf, "{}", ty.display(db)); | ||
86 | res.push_param(&buf); | ||
87 | } | ||
44 | } | 88 | } |
89 | res.signature.push(')'); | ||
90 | |||
91 | match callable.kind() { | ||
92 | hir::CallableKind::Function(_) => { | ||
93 | let ret_type = callable.return_type(); | ||
94 | if !ret_type.is_unit() { | ||
95 | format_to!(res.signature, " -> {}", ret_type.display(db)); | ||
96 | } | ||
97 | } | ||
98 | hir::CallableKind::TupleStruct(_) | hir::CallableKind::TupleEnumVariant(_) => {} | ||
99 | } | ||
100 | Some(res) | ||
45 | } | 101 | } |
46 | 102 | ||
47 | fn call_info_for_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Option<CallInfo> { | 103 | fn call_info_impl( |
104 | sema: &Semantics<RootDatabase>, | ||
105 | token: SyntaxToken, | ||
106 | ) -> Option<(hir::Callable, Option<usize>)> { | ||
48 | // Find the calling expression and it's NameRef | 107 | // Find the calling expression and it's NameRef |
49 | let calling_node = FnCallNode::with_node(&token.parent())?; | 108 | let calling_node = FnCallNode::with_node(&token.parent())?; |
50 | 109 | ||
51 | let signature = match &calling_node { | 110 | let callable = match &calling_node { |
52 | FnCallNode::CallExpr(call) => { | 111 | FnCallNode::CallExpr(call) => sema.type_of_expr(&call.expr()?)?.as_callable(sema.db)?, |
53 | //FIXME: Type::as_callable is broken | 112 | FnCallNode::MethodCallExpr(call) => sema.resolve_method_call_as_callable(call)?, |
54 | let callable_def = sema.type_of_expr(&call.expr()?)?.as_callable()?; | 113 | }; |
55 | match callable_def { | 114 | let active_param = if let Some(arg_list) = calling_node.arg_list() { |
56 | hir::CallableDefId::FunctionId(it) => { | 115 | // Number of arguments specified at the call site |
57 | let fn_def = it.into(); | 116 | let num_args_at_callsite = arg_list.args().count(); |
58 | FunctionSignature::from_hir(sema.db, fn_def) | 117 | |
59 | } | 118 | let arg_list_range = arg_list.syntax().text_range(); |
60 | hir::CallableDefId::StructId(it) => { | 119 | if !arg_list_range.contains_inclusive(token.text_range().start()) { |
61 | FunctionSignature::from_struct(sema.db, it.into())? | 120 | mark::hit!(call_info_bad_offset); |
62 | } | 121 | return None; |
63 | hir::CallableDefId::EnumVariantId(it) => { | ||
64 | FunctionSignature::from_enum_variant(sema.db, it.into())? | ||
65 | } | ||
66 | } | ||
67 | } | ||
68 | FnCallNode::MethodCallExpr(method_call) => { | ||
69 | let function = sema.resolve_method_call(&method_call)?; | ||
70 | FunctionSignature::from_hir(sema.db, function) | ||
71 | } | ||
72 | FnCallNode::MacroCallExpr(macro_call) => { | ||
73 | let macro_def = sema.resolve_macro_call(¯o_call)?; | ||
74 | FunctionSignature::from_macro(sema.db, macro_def)? | ||
75 | } | 122 | } |
123 | let param = std::cmp::min( | ||
124 | num_args_at_callsite, | ||
125 | arg_list | ||
126 | .args() | ||
127 | .take_while(|arg| arg.syntax().text_range().end() <= token.text_range().start()) | ||
128 | .count(), | ||
129 | ); | ||
130 | |||
131 | Some(param) | ||
132 | } else { | ||
133 | None | ||
76 | }; | 134 | }; |
135 | Some((callable, active_param)) | ||
136 | } | ||
77 | 137 | ||
78 | // If we have a calling expression let's find which argument we are on | 138 | #[derive(Debug)] |
79 | let num_params = signature.parameters.len(); | 139 | pub(crate) struct ActiveParameter { |
80 | 140 | pub(crate) ty: Type, | |
81 | let active_parameter = match num_params { | 141 | pub(crate) name: String, |
82 | 0 => None, | 142 | } |
83 | 1 if signature.has_self_param => None, | ||
84 | 1 => Some(0), | ||
85 | _ => { | ||
86 | if let Some(arg_list) = calling_node.arg_list() { | ||
87 | // Number of arguments specified at the call site | ||
88 | let num_args_at_callsite = arg_list.args().count(); | ||
89 | |||
90 | let arg_list_range = arg_list.syntax().text_range(); | ||
91 | if !arg_list_range.contains_inclusive(token.text_range().start()) { | ||
92 | mark::hit!(call_info_bad_offset); | ||
93 | return None; | ||
94 | } | ||
95 | 143 | ||
96 | let mut param = std::cmp::min( | 144 | impl ActiveParameter { |
97 | num_args_at_callsite, | 145 | pub(crate) fn at(db: &RootDatabase, position: FilePosition) -> Option<Self> { |
98 | arg_list | 146 | let sema = Semantics::new(db); |
99 | .args() | 147 | let file = sema.parse(position.file_id); |
100 | .take_while(|arg| { | 148 | let file = file.syntax(); |
101 | arg.syntax().text_range().end() <= token.text_range().start() | 149 | let token = file.token_at_offset(position.offset).next()?; |
102 | }) | 150 | let token = sema.descend_into_macros(token); |
103 | .count(), | 151 | Self::at_token(&sema, token) |
104 | ); | 152 | } |
105 | |||
106 | // If we are in a method account for `self` | ||
107 | if signature.has_self_param { | ||
108 | param += 1; | ||
109 | } | ||
110 | 153 | ||
111 | Some(param) | 154 | pub(crate) fn at_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Option<Self> { |
112 | } else { | 155 | let (signature, active_parameter) = call_info_impl(&sema, token)?; |
113 | None | ||
114 | } | ||
115 | } | ||
116 | }; | ||
117 | 156 | ||
118 | Some(CallInfo { signature, active_parameter }) | 157 | let idx = active_parameter?; |
158 | let mut params = signature.params(sema.db); | ||
159 | let (pat, ty) = params.swap_remove(idx); | ||
160 | let name = pat?.to_string(); | ||
161 | Some(ActiveParameter { ty, name }) | ||
162 | } | ||
119 | } | 163 | } |
120 | 164 | ||
121 | #[derive(Debug)] | 165 | #[derive(Debug)] |
122 | pub(crate) enum FnCallNode { | 166 | pub(crate) enum FnCallNode { |
123 | CallExpr(ast::CallExpr), | 167 | CallExpr(ast::CallExpr), |
124 | MethodCallExpr(ast::MethodCallExpr), | 168 | MethodCallExpr(ast::MethodCallExpr), |
125 | MacroCallExpr(ast::MacroCall), | ||
126 | } | 169 | } |
127 | 170 | ||
128 | impl FnCallNode { | 171 | impl FnCallNode { |
@@ -138,7 +181,6 @@ impl FnCallNode { | |||
138 | } | 181 | } |
139 | Some(FnCallNode::MethodCallExpr(it)) | 182 | Some(FnCallNode::MethodCallExpr(it)) |
140 | }, | 183 | }, |
141 | ast::MacroCall(it) => Some(FnCallNode::MacroCallExpr(it)), | ||
142 | _ => None, | 184 | _ => None, |
143 | } | 185 | } |
144 | } | 186 | } |
@@ -150,7 +192,6 @@ impl FnCallNode { | |||
150 | match node { | 192 | match node { |
151 | ast::CallExpr(it) => Some(FnCallNode::CallExpr(it)), | 193 | ast::CallExpr(it) => Some(FnCallNode::CallExpr(it)), |
152 | ast::MethodCallExpr(it) => Some(FnCallNode::MethodCallExpr(it)), | 194 | ast::MethodCallExpr(it) => Some(FnCallNode::MethodCallExpr(it)), |
153 | ast::MacroCall(it) => Some(FnCallNode::MacroCallExpr(it)), | ||
154 | _ => None, | 195 | _ => None, |
155 | } | 196 | } |
156 | } | 197 | } |
@@ -166,8 +207,6 @@ impl FnCallNode { | |||
166 | FnCallNode::MethodCallExpr(call_expr) => { | 207 | FnCallNode::MethodCallExpr(call_expr) => { |
167 | call_expr.syntax().children().filter_map(ast::NameRef::cast).next() | 208 | call_expr.syntax().children().filter_map(ast::NameRef::cast).next() |
168 | } | 209 | } |
169 | |||
170 | FnCallNode::MacroCallExpr(call_expr) => call_expr.path()?.segment()?.name_ref(), | ||
171 | } | 210 | } |
172 | } | 211 | } |
173 | 212 | ||
@@ -175,21 +214,10 @@ impl FnCallNode { | |||
175 | match self { | 214 | match self { |
176 | FnCallNode::CallExpr(expr) => expr.arg_list(), | 215 | FnCallNode::CallExpr(expr) => expr.arg_list(), |
177 | FnCallNode::MethodCallExpr(expr) => expr.arg_list(), | 216 | FnCallNode::MethodCallExpr(expr) => expr.arg_list(), |
178 | FnCallNode::MacroCallExpr(_) => None, | ||
179 | } | 217 | } |
180 | } | 218 | } |
181 | } | 219 | } |
182 | 220 | ||
183 | impl CallInfo { | ||
184 | fn into_active_parameter(self) -> Option<ActiveParameter> { | ||
185 | let idx = self.active_parameter?; | ||
186 | let ty = self.signature.parameter_types.get(idx)?.clone(); | ||
187 | let name = self.signature.parameter_names.get(idx)?.clone(); | ||
188 | let res = ActiveParameter { ty, name }; | ||
189 | Some(res) | ||
190 | } | ||
191 | } | ||
192 | |||
193 | #[cfg(test)] | 221 | #[cfg(test)] |
194 | mod tests { | 222 | mod tests { |
195 | use expect::{expect, Expect}; | 223 | use expect::{expect, Expect}; |
@@ -202,20 +230,18 @@ mod tests { | |||
202 | let call_info = analysis.call_info(position).unwrap(); | 230 | let call_info = analysis.call_info(position).unwrap(); |
203 | let actual = match call_info { | 231 | let actual = match call_info { |
204 | Some(call_info) => { | 232 | Some(call_info) => { |
205 | let docs = match &call_info.signature.doc { | 233 | let docs = match &call_info.doc { |
206 | None => "".to_string(), | 234 | None => "".to_string(), |
207 | Some(docs) => format!("{}\n------\n", docs.as_str()), | 235 | Some(docs) => format!("{}\n------\n", docs.as_str()), |
208 | }; | 236 | }; |
209 | let params = call_info | 237 | let params = call_info |
210 | .signature | 238 | .parameter_labels() |
211 | .parameters | ||
212 | .iter() | ||
213 | .enumerate() | 239 | .enumerate() |
214 | .map(|(i, param)| { | 240 | .map(|(i, param)| { |
215 | if Some(i) == call_info.active_parameter { | 241 | if Some(i) == call_info.active_parameter { |
216 | format!("<{}>", param) | 242 | format!("<{}>", param) |
217 | } else { | 243 | } else { |
218 | param.clone() | 244 | param.to_string() |
219 | } | 245 | } |
220 | }) | 246 | }) |
221 | .collect::<Vec<_>>() | 247 | .collect::<Vec<_>>() |
@@ -296,10 +322,8 @@ fn foo<T, U: Copy + Display>(x: T, y: U) -> u32 | |||
296 | fn bar() { foo(<|>3, ); } | 322 | fn bar() { foo(<|>3, ); } |
297 | "#, | 323 | "#, |
298 | expect![[r#" | 324 | expect![[r#" |
299 | fn foo<T, U: Copy + Display>(x: T, y: U) -> u32 | 325 | fn foo(x: i32, y: {unknown}) -> u32 |
300 | where T: Copy + Display, | 326 | (<x: i32>, y: {unknown}) |
301 | U: Debug | ||
302 | (<x: T>, y: U) | ||
303 | "#]], | 327 | "#]], |
304 | ); | 328 | ); |
305 | } | 329 | } |
@@ -312,8 +336,7 @@ fn foo<T>() -> T where T: Copy + Display {} | |||
312 | fn bar() { foo(<|>); } | 336 | fn bar() { foo(<|>); } |
313 | "#, | 337 | "#, |
314 | expect![[r#" | 338 | expect![[r#" |
315 | fn foo<T>() -> T | 339 | fn foo() -> {unknown} |
316 | where T: Copy + Display | ||
317 | () | 340 | () |
318 | "#]], | 341 | "#]], |
319 | ); | 342 | ); |
@@ -323,11 +346,14 @@ fn bar() { foo(<|>); } | |||
323 | fn test_fn_signature_for_impl() { | 346 | fn test_fn_signature_for_impl() { |
324 | check( | 347 | check( |
325 | r#" | 348 | r#" |
326 | struct F; impl F { pub fn new() { F{}} } | 349 | struct F; |
327 | fn bar() {let _ : F = F::new(<|>);} | 350 | impl F { pub fn new() { } } |
351 | fn bar() { | ||
352 | let _ : F = F::new(<|>); | ||
353 | } | ||
328 | "#, | 354 | "#, |
329 | expect![[r#" | 355 | expect![[r#" |
330 | pub fn new() | 356 | fn new() |
331 | () | 357 | () |
332 | "#]], | 358 | "#]], |
333 | ); | 359 | ); |
@@ -346,8 +372,8 @@ fn bar() { | |||
346 | } | 372 | } |
347 | "#, | 373 | "#, |
348 | expect![[r#" | 374 | expect![[r#" |
349 | pub fn do_it(&self) | 375 | fn do_it(&self) |
350 | (&self) | 376 | () |
351 | "#]], | 377 | "#]], |
352 | ); | 378 | ); |
353 | } | 379 | } |
@@ -365,8 +391,8 @@ fn bar() { | |||
365 | } | 391 | } |
366 | "#, | 392 | "#, |
367 | expect![[r#" | 393 | expect![[r#" |
368 | pub fn do_it(&self, x: i32) | 394 | fn do_it(&self, x: i32) |
369 | (&self, <x: i32>) | 395 | (<x: i32>) |
370 | "#]], | 396 | "#]], |
371 | ); | 397 | ); |
372 | } | 398 | } |
@@ -425,7 +451,7 @@ pub fn do() { | |||
425 | assert_eq!(6, my_crate::add_one(5)); | 451 | assert_eq!(6, my_crate::add_one(5)); |
426 | ``` | 452 | ``` |
427 | ------ | 453 | ------ |
428 | pub fn add_one(x: i32) -> i32 | 454 | fn add_one(x: i32) -> i32 |
429 | (<x: i32>) | 455 | (<x: i32>) |
430 | "##]], | 456 | "##]], |
431 | ); | 457 | ); |
@@ -467,7 +493,7 @@ pub fn do_it() { | |||
467 | assert_eq!(6, my_crate::add_one(5)); | 493 | assert_eq!(6, my_crate::add_one(5)); |
468 | ``` | 494 | ``` |
469 | ------ | 495 | ------ |
470 | pub fn add_one(x: i32) -> i32 | 496 | fn add_one(x: i32) -> i32 |
471 | (<x: i32>) | 497 | (<x: i32>) |
472 | "##]], | 498 | "##]], |
473 | ); | 499 | ); |
@@ -505,8 +531,8 @@ pub fn foo(mut r: WriteHandler<()>) { | |||
505 | 531 | ||
506 | By default this method stops actor's `Context`. | 532 | By default this method stops actor's `Context`. |
507 | ------ | 533 | ------ |
508 | fn finished(&mut self, ctx: &mut Self::Context) | 534 | fn finished(&mut self, ctx: &mut {unknown}) |
509 | (&mut self, <ctx: &mut Self::Context>) | 535 | (<ctx: &mut {unknown}>) |
510 | "#]], | 536 | "#]], |
511 | ); | 537 | ); |
512 | } | 538 | } |
@@ -539,7 +565,7 @@ fn main() { | |||
539 | "#, | 565 | "#, |
540 | expect![[r#" | 566 | expect![[r#" |
541 | fn bar(&self, _: u32) | 567 | fn bar(&self, _: u32) |
542 | (&self, <_: u32>) | 568 | (<_: u32>) |
543 | "#]], | 569 | "#]], |
544 | ); | 570 | ); |
545 | } | 571 | } |
@@ -549,15 +575,15 @@ fn main() { | |||
549 | check( | 575 | check( |
550 | r#" | 576 | r#" |
551 | /// A cool tuple struct | 577 | /// A cool tuple struct |
552 | struct TS(u32, i32); | 578 | struct S(u32, i32); |
553 | fn main() { | 579 | fn main() { |
554 | let s = TS(0, <|>); | 580 | let s = S(0, <|>); |
555 | } | 581 | } |
556 | "#, | 582 | "#, |
557 | expect![[r#" | 583 | expect![[r#" |
558 | A cool tuple struct | 584 | A cool tuple struct |
559 | ------ | 585 | ------ |
560 | struct TS(u32, i32) -> TS | 586 | struct S(u32, i32) |
561 | (u32, <i32>) | 587 | (u32, <i32>) |
562 | "#]], | 588 | "#]], |
563 | ); | 589 | ); |
@@ -567,32 +593,19 @@ fn main() { | |||
567 | fn generic_struct() { | 593 | fn generic_struct() { |
568 | check( | 594 | check( |
569 | r#" | 595 | r#" |
570 | struct TS<T>(T); | 596 | struct S<T>(T); |
571 | fn main() { | 597 | fn main() { |
572 | let s = TS(<|>); | 598 | let s = S(<|>); |
573 | } | 599 | } |
574 | "#, | 600 | "#, |
575 | expect![[r#" | 601 | expect![[r#" |
576 | struct TS<T>(T) -> TS | 602 | struct S({unknown}) |
577 | (<T>) | 603 | (<{unknown}>) |
578 | "#]], | 604 | "#]], |
579 | ); | 605 | ); |
580 | } | 606 | } |
581 | 607 | ||
582 | #[test] | 608 | #[test] |
583 | fn cant_call_named_structs() { | ||
584 | check( | ||
585 | r#" | ||
586 | struct TS { x: u32, y: i32 } | ||
587 | fn main() { | ||
588 | let s = TS(<|>); | ||
589 | } | ||
590 | "#, | ||
591 | expect![[""]], | ||
592 | ); | ||
593 | } | ||
594 | |||
595 | #[test] | ||
596 | fn works_for_enum_variants() { | 609 | fn works_for_enum_variants() { |
597 | check( | 610 | check( |
598 | r#" | 611 | r#" |
@@ -612,27 +625,19 @@ fn main() { | |||
612 | expect![[r#" | 625 | expect![[r#" |
613 | A Variant | 626 | A Variant |
614 | ------ | 627 | ------ |
615 | E::A(0: i32) | 628 | enum E::A(i32) |
616 | (<0: i32>) | 629 | (<i32>) |
617 | "#]], | 630 | "#]], |
618 | ); | 631 | ); |
619 | } | 632 | } |
620 | 633 | ||
621 | #[test] | 634 | #[test] |
622 | fn cant_call_enum_records() { | 635 | fn cant_call_struct_record() { |
623 | check( | 636 | check( |
624 | r#" | 637 | r#" |
625 | enum E { | 638 | struct S { x: u32, y: i32 } |
626 | /// A Variant | ||
627 | A(i32), | ||
628 | /// Another | ||
629 | B, | ||
630 | /// And C | ||
631 | C { a: i32, b: i32 } | ||
632 | } | ||
633 | |||
634 | fn main() { | 639 | fn main() { |
635 | let a = E::C(<|>); | 640 | let s = S(<|>); |
636 | } | 641 | } |
637 | "#, | 642 | "#, |
638 | expect![[""]], | 643 | expect![[""]], |
@@ -640,24 +645,23 @@ fn main() { | |||
640 | } | 645 | } |
641 | 646 | ||
642 | #[test] | 647 | #[test] |
643 | fn fn_signature_for_macro() { | 648 | fn cant_call_enum_record() { |
644 | check( | 649 | check( |
645 | r#" | 650 | r#" |
646 | /// empty macro | 651 | enum E { |
647 | macro_rules! foo { | 652 | /// A Variant |
648 | () => {} | 653 | A(i32), |
654 | /// Another | ||
655 | B, | ||
656 | /// And C | ||
657 | C { a: i32, b: i32 } | ||
649 | } | 658 | } |
650 | 659 | ||
651 | fn f() { | 660 | fn main() { |
652 | foo!(<|>); | 661 | let a = E::C(<|>); |
653 | } | 662 | } |
654 | "#, | 663 | "#, |
655 | expect![[r#" | 664 | expect![[""]], |
656 | empty macro | ||
657 | ------ | ||
658 | foo!() | ||
659 | () | ||
660 | "#]], | ||
661 | ); | 665 | ); |
662 | } | 666 | } |
663 | 667 | ||
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index 64349dcb8..e6b4737aa 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs | |||
@@ -329,15 +329,10 @@ pub(crate) fn compute_score( | |||
329 | ty: &Type, | 329 | ty: &Type, |
330 | name: &str, | 330 | name: &str, |
331 | ) -> Option<CompletionScore> { | 331 | ) -> Option<CompletionScore> { |
332 | // FIXME: this should not fall back to string equality. | ||
333 | let ty = &ty.display(ctx.db).to_string(); | ||
334 | let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax { | 332 | let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax { |
335 | mark::hit!(record_field_type_match); | 333 | mark::hit!(record_field_type_match); |
336 | let (struct_field, _local) = ctx.sema.resolve_record_field(record_field)?; | 334 | let (struct_field, _local) = ctx.sema.resolve_record_field(record_field)?; |
337 | ( | 335 | (struct_field.name(ctx.db).to_string(), struct_field.signature_ty(ctx.db)) |
338 | struct_field.name(ctx.db).to_string(), | ||
339 | struct_field.signature_ty(ctx.db).display(ctx.db).to_string(), | ||
340 | ) | ||
341 | } else if let Some(active_parameter) = &ctx.active_parameter { | 336 | } else if let Some(active_parameter) = &ctx.active_parameter { |
342 | mark::hit!(active_param_type_match); | 337 | mark::hit!(active_param_type_match); |
343 | (active_parameter.name.clone(), active_parameter.ty.clone()) | 338 | (active_parameter.name.clone(), active_parameter.ty.clone()) |
diff --git a/crates/ra_ide/src/display/function_signature.rs b/crates/ra_ide/src/display/function_signature.rs index 1d39544d3..709a85f65 100644 --- a/crates/ra_ide/src/display/function_signature.rs +++ b/crates/ra_ide/src/display/function_signature.rs | |||
@@ -149,27 +149,6 @@ impl FunctionSignature { | |||
149 | has_self_param: false, | 149 | has_self_param: false, |
150 | }) | 150 | }) |
151 | } | 151 | } |
152 | |||
153 | pub(crate) fn from_macro(db: &RootDatabase, macro_def: hir::MacroDef) -> Option<Self> { | ||
154 | let node: ast::MacroCall = macro_def.source(db).value; | ||
155 | |||
156 | let params = vec![]; | ||
157 | |||
158 | Some(FunctionSignature { | ||
159 | kind: CallableKind::Macro, | ||
160 | visibility: None, | ||
161 | qualifier: Default::default(), | ||
162 | name: node.name().map(|n| n.text().to_string()), | ||
163 | ret_type: None, | ||
164 | parameters: params, | ||
165 | parameter_names: vec![], | ||
166 | parameter_types: vec![], | ||
167 | generic_parameters: vec![], | ||
168 | where_predicates: vec![], | ||
169 | doc: macro_def.docs(db), | ||
170 | has_self_param: false, | ||
171 | }) | ||
172 | } | ||
173 | } | 152 | } |
174 | 153 | ||
175 | impl From<&'_ ast::FnDef> for FunctionSignature { | 154 | impl From<&'_ ast::FnDef> for FunctionSignature { |
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 3cbae8a45..2e021f032 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs | |||
@@ -322,15 +322,15 @@ fn get_fn_signature(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option< | |||
322 | match expr { | 322 | match expr { |
323 | ast::Expr::CallExpr(expr) => { | 323 | ast::Expr::CallExpr(expr) => { |
324 | // FIXME: Type::as_callable is broken for closures | 324 | // FIXME: Type::as_callable is broken for closures |
325 | let callable_def = sema.type_of_expr(&expr.expr()?)?.as_callable()?; | 325 | let callable = sema.type_of_expr(&expr.expr()?)?.as_callable(sema.db)?; |
326 | match callable_def { | 326 | match callable.kind() { |
327 | hir::CallableDefId::FunctionId(it) => { | 327 | hir::CallableKind::Function(it) => { |
328 | Some(FunctionSignature::from_hir(sema.db, it.into())) | 328 | Some(FunctionSignature::from_hir(sema.db, it.into())) |
329 | } | 329 | } |
330 | hir::CallableDefId::StructId(it) => { | 330 | hir::CallableKind::TupleStruct(it) => { |
331 | FunctionSignature::from_struct(sema.db, it.into()) | 331 | FunctionSignature::from_struct(sema.db, it.into()) |
332 | } | 332 | } |
333 | hir::CallableDefId::EnumVariantId(it) => { | 333 | hir::CallableKind::TupleEnumVariant(it) => { |
334 | FunctionSignature::from_enum_variant(sema.db, it.into()) | 334 | FunctionSignature::from_enum_variant(sema.db, it.into()) |
335 | } | 335 | } |
336 | } | 336 | } |