diff options
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r-- | crates/ra_ide/src/call_hierarchy.rs | 10 | ||||
-rw-r--r-- | crates/ra_ide/src/call_info.rs | 361 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_trait_impl.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/presentation.rs | 9 | ||||
-rw-r--r-- | crates/ra_ide/src/display.rs | 11 | ||||
-rw-r--r-- | crates/ra_ide/src/display/function_signature.rs | 61 | ||||
-rw-r--r-- | crates/ra_ide/src/file_structure.rs (renamed from crates/ra_ide/src/display/structure.rs) | 0 | ||||
-rw-r--r-- | crates/ra_ide/src/inlay_hints.rs | 14 | ||||
-rw-r--r-- | crates/ra_ide/src/lib.rs | 37 |
9 files changed, 249 insertions, 256 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..35a8a0dc5 100644 --- a/crates/ra_ide/src/call_info.rs +++ b/crates/ra_ide/src/call_info.rs | |||
@@ -1,20 +1,42 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | use hir::Semantics; | 2 | use either::Either; |
3 | use hir::{Docs, HirDisplay, Semantics, Type}; | ||
3 | use ra_ide_db::RootDatabase; | 4 | use ra_ide_db::RootDatabase; |
4 | use ra_syntax::{ | 5 | use ra_syntax::{ |
5 | ast::{self, ArgListOwner}, | 6 | ast::{self, ArgListOwner}, |
6 | match_ast, AstNode, SyntaxNode, SyntaxToken, | 7 | match_ast, AstNode, SyntaxNode, SyntaxToken, TextRange, TextSize, |
7 | }; | 8 | }; |
9 | use stdx::format_to; | ||
8 | use test_utils::mark; | 10 | use test_utils::mark; |
9 | 11 | ||
10 | use crate::{FilePosition, FunctionSignature}; | 12 | use crate::FilePosition; |
11 | 13 | ||
12 | /// Contains information about a call site. Specifically the | 14 | /// Contains information about a call site. Specifically the |
13 | /// `FunctionSignature`and current parameter. | 15 | /// `FunctionSignature`and current parameter. |
14 | #[derive(Debug)] | 16 | #[derive(Debug)] |
15 | pub struct CallInfo { | 17 | pub struct CallInfo { |
16 | pub signature: FunctionSignature, | 18 | pub doc: Option<String>, |
19 | pub signature: String, | ||
17 | pub active_parameter: Option<usize>, | 20 | pub active_parameter: Option<usize>, |
21 | parameters: Vec<TextRange>, | ||
22 | } | ||
23 | |||
24 | impl CallInfo { | ||
25 | pub fn parameter_labels(&self) -> impl Iterator<Item = &str> + '_ { | ||
26 | self.parameters.iter().map(move |&it| &self.signature[it]) | ||
27 | } | ||
28 | pub fn parameter_ranges(&self) -> &[TextRange] { | ||
29 | &self.parameters | ||
30 | } | ||
31 | fn push_param(&mut self, param: &str) { | ||
32 | if !self.signature.ends_with('(') { | ||
33 | self.signature.push_str(", "); | ||
34 | } | ||
35 | let start = TextSize::of(&self.signature); | ||
36 | self.signature.push_str(param); | ||
37 | let end = TextSize::of(&self.signature); | ||
38 | self.parameters.push(TextRange::new(start, end)) | ||
39 | } | ||
18 | } | 40 | } |
19 | 41 | ||
20 | /// Computes parameter information for the given call expression. | 42 | /// Computes parameter information for the given call expression. |
@@ -24,105 +46,130 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal | |||
24 | let file = file.syntax(); | 46 | let file = file.syntax(); |
25 | let token = file.token_at_offset(position.offset).next()?; | 47 | let token = file.token_at_offset(position.offset).next()?; |
26 | let token = sema.descend_into_macros(token); | 48 | let token = sema.descend_into_macros(token); |
27 | call_info_for_token(&sema, token) | ||
28 | } | ||
29 | 49 | ||
30 | #[derive(Debug)] | 50 | 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 | 51 | ||
37 | impl ActiveParameter { | 52 | let mut res = |
38 | pub(crate) fn at(db: &RootDatabase, position: FilePosition) -> Option<Self> { | 53 | CallInfo { doc: None, signature: String::new(), parameters: vec![], active_parameter }; |
39 | call_info(db, position)?.into_active_parameter() | 54 | |
55 | match callable.kind() { | ||
56 | hir::CallableKind::Function(func) => { | ||
57 | res.doc = func.docs(db).map(|it| it.as_str().to_string()); | ||
58 | format_to!(res.signature, "fn {}", func.name(db)); | ||
59 | } | ||
60 | hir::CallableKind::TupleStruct(strukt) => { | ||
61 | res.doc = strukt.docs(db).map(|it| it.as_str().to_string()); | ||
62 | format_to!(res.signature, "struct {}", strukt.name(db)); | ||
63 | } | ||
64 | hir::CallableKind::TupleEnumVariant(variant) => { | ||
65 | res.doc = variant.docs(db).map(|it| it.as_str().to_string()); | ||
66 | format_to!( | ||
67 | res.signature, | ||
68 | "enum {}::{}", | ||
69 | variant.parent_enum(db).name(db), | ||
70 | variant.name(db) | ||
71 | ); | ||
72 | } | ||
40 | } | 73 | } |
41 | 74 | ||
42 | pub(crate) fn at_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Option<Self> { | 75 | res.signature.push('('); |
43 | call_info_for_token(sema, token)?.into_active_parameter() | 76 | { |
77 | if let Some(self_param) = callable.receiver_param(db) { | ||
78 | format_to!(res.signature, "{}", self_param) | ||
79 | } | ||
80 | let mut buf = String::new(); | ||
81 | for (pat, ty) in callable.params(db) { | ||
82 | buf.clear(); | ||
83 | if let Some(pat) = pat { | ||
84 | match pat { | ||
85 | Either::Left(_self) => format_to!(buf, "self: "), | ||
86 | Either::Right(pat) => format_to!(buf, "{}: ", pat), | ||
87 | } | ||
88 | } | ||
89 | format_to!(buf, "{}", ty.display(db)); | ||
90 | res.push_param(&buf); | ||
91 | } | ||
44 | } | 92 | } |
93 | res.signature.push(')'); | ||
94 | |||
95 | match callable.kind() { | ||
96 | hir::CallableKind::Function(_) => { | ||
97 | let ret_type = callable.return_type(); | ||
98 | if !ret_type.is_unit() { | ||
99 | format_to!(res.signature, " -> {}", ret_type.display(db)); | ||
100 | } | ||
101 | } | ||
102 | hir::CallableKind::TupleStruct(_) | hir::CallableKind::TupleEnumVariant(_) => {} | ||
103 | } | ||
104 | Some(res) | ||
45 | } | 105 | } |
46 | 106 | ||
47 | fn call_info_for_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Option<CallInfo> { | 107 | fn call_info_impl( |
108 | sema: &Semantics<RootDatabase>, | ||
109 | token: SyntaxToken, | ||
110 | ) -> Option<(hir::Callable, Option<usize>)> { | ||
48 | // Find the calling expression and it's NameRef | 111 | // Find the calling expression and it's NameRef |
49 | let calling_node = FnCallNode::with_node(&token.parent())?; | 112 | let calling_node = FnCallNode::with_node(&token.parent())?; |
50 | 113 | ||
51 | let signature = match &calling_node { | 114 | let callable = match &calling_node { |
52 | FnCallNode::CallExpr(call) => { | 115 | FnCallNode::CallExpr(call) => sema.type_of_expr(&call.expr()?)?.as_callable(sema.db)?, |
53 | //FIXME: Type::as_callable is broken | 116 | FnCallNode::MethodCallExpr(call) => sema.resolve_method_call_as_callable(call)?, |
54 | let callable_def = sema.type_of_expr(&call.expr()?)?.as_callable()?; | 117 | }; |
55 | match callable_def { | 118 | let active_param = if let Some(arg_list) = calling_node.arg_list() { |
56 | hir::CallableDefId::FunctionId(it) => { | 119 | // Number of arguments specified at the call site |
57 | let fn_def = it.into(); | 120 | let num_args_at_callsite = arg_list.args().count(); |
58 | FunctionSignature::from_hir(sema.db, fn_def) | 121 | |
59 | } | 122 | let arg_list_range = arg_list.syntax().text_range(); |
60 | hir::CallableDefId::StructId(it) => { | 123 | if !arg_list_range.contains_inclusive(token.text_range().start()) { |
61 | FunctionSignature::from_struct(sema.db, it.into())? | 124 | mark::hit!(call_info_bad_offset); |
62 | } | 125 | 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 | } | 126 | } |
127 | let param = std::cmp::min( | ||
128 | num_args_at_callsite, | ||
129 | arg_list | ||
130 | .args() | ||
131 | .take_while(|arg| arg.syntax().text_range().end() <= token.text_range().start()) | ||
132 | .count(), | ||
133 | ); | ||
134 | |||
135 | Some(param) | ||
136 | } else { | ||
137 | None | ||
76 | }; | 138 | }; |
139 | Some((callable, active_param)) | ||
140 | } | ||
77 | 141 | ||
78 | // If we have a calling expression let's find which argument we are on | 142 | #[derive(Debug)] |
79 | let num_params = signature.parameters.len(); | 143 | pub(crate) struct ActiveParameter { |
80 | 144 | pub(crate) ty: Type, | |
81 | let active_parameter = match num_params { | 145 | pub(crate) name: String, |
82 | 0 => None, | 146 | } |
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 | 147 | ||
96 | let mut param = std::cmp::min( | 148 | impl ActiveParameter { |
97 | num_args_at_callsite, | 149 | pub(crate) fn at(db: &RootDatabase, position: FilePosition) -> Option<Self> { |
98 | arg_list | 150 | let sema = Semantics::new(db); |
99 | .args() | 151 | let file = sema.parse(position.file_id); |
100 | .take_while(|arg| { | 152 | let file = file.syntax(); |
101 | arg.syntax().text_range().end() <= token.text_range().start() | 153 | let token = file.token_at_offset(position.offset).next()?; |
102 | }) | 154 | let token = sema.descend_into_macros(token); |
103 | .count(), | 155 | Self::at_token(&sema, token) |
104 | ); | 156 | } |
105 | |||
106 | // If we are in a method account for `self` | ||
107 | if signature.has_self_param { | ||
108 | param += 1; | ||
109 | } | ||
110 | 157 | ||
111 | Some(param) | 158 | pub(crate) fn at_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Option<Self> { |
112 | } else { | 159 | let (signature, active_parameter) = call_info_impl(&sema, token)?; |
113 | None | ||
114 | } | ||
115 | } | ||
116 | }; | ||
117 | 160 | ||
118 | Some(CallInfo { signature, active_parameter }) | 161 | let idx = active_parameter?; |
162 | let mut params = signature.params(sema.db); | ||
163 | let (pat, ty) = params.swap_remove(idx); | ||
164 | let name = pat?.to_string(); | ||
165 | Some(ActiveParameter { ty, name }) | ||
166 | } | ||
119 | } | 167 | } |
120 | 168 | ||
121 | #[derive(Debug)] | 169 | #[derive(Debug)] |
122 | pub(crate) enum FnCallNode { | 170 | pub(crate) enum FnCallNode { |
123 | CallExpr(ast::CallExpr), | 171 | CallExpr(ast::CallExpr), |
124 | MethodCallExpr(ast::MethodCallExpr), | 172 | MethodCallExpr(ast::MethodCallExpr), |
125 | MacroCallExpr(ast::MacroCall), | ||
126 | } | 173 | } |
127 | 174 | ||
128 | impl FnCallNode { | 175 | impl FnCallNode { |
@@ -138,7 +185,6 @@ impl FnCallNode { | |||
138 | } | 185 | } |
139 | Some(FnCallNode::MethodCallExpr(it)) | 186 | Some(FnCallNode::MethodCallExpr(it)) |
140 | }, | 187 | }, |
141 | ast::MacroCall(it) => Some(FnCallNode::MacroCallExpr(it)), | ||
142 | _ => None, | 188 | _ => None, |
143 | } | 189 | } |
144 | } | 190 | } |
@@ -150,7 +196,6 @@ impl FnCallNode { | |||
150 | match node { | 196 | match node { |
151 | ast::CallExpr(it) => Some(FnCallNode::CallExpr(it)), | 197 | ast::CallExpr(it) => Some(FnCallNode::CallExpr(it)), |
152 | ast::MethodCallExpr(it) => Some(FnCallNode::MethodCallExpr(it)), | 198 | ast::MethodCallExpr(it) => Some(FnCallNode::MethodCallExpr(it)), |
153 | ast::MacroCall(it) => Some(FnCallNode::MacroCallExpr(it)), | ||
154 | _ => None, | 199 | _ => None, |
155 | } | 200 | } |
156 | } | 201 | } |
@@ -166,8 +211,6 @@ impl FnCallNode { | |||
166 | FnCallNode::MethodCallExpr(call_expr) => { | 211 | FnCallNode::MethodCallExpr(call_expr) => { |
167 | call_expr.syntax().children().filter_map(ast::NameRef::cast).next() | 212 | call_expr.syntax().children().filter_map(ast::NameRef::cast).next() |
168 | } | 213 | } |
169 | |||
170 | FnCallNode::MacroCallExpr(call_expr) => call_expr.path()?.segment()?.name_ref(), | ||
171 | } | 214 | } |
172 | } | 215 | } |
173 | 216 | ||
@@ -175,21 +218,10 @@ impl FnCallNode { | |||
175 | match self { | 218 | match self { |
176 | FnCallNode::CallExpr(expr) => expr.arg_list(), | 219 | FnCallNode::CallExpr(expr) => expr.arg_list(), |
177 | FnCallNode::MethodCallExpr(expr) => expr.arg_list(), | 220 | FnCallNode::MethodCallExpr(expr) => expr.arg_list(), |
178 | FnCallNode::MacroCallExpr(_) => None, | ||
179 | } | 221 | } |
180 | } | 222 | } |
181 | } | 223 | } |
182 | 224 | ||
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)] | 225 | #[cfg(test)] |
194 | mod tests { | 226 | mod tests { |
195 | use expect::{expect, Expect}; | 227 | use expect::{expect, Expect}; |
@@ -202,20 +234,18 @@ mod tests { | |||
202 | let call_info = analysis.call_info(position).unwrap(); | 234 | let call_info = analysis.call_info(position).unwrap(); |
203 | let actual = match call_info { | 235 | let actual = match call_info { |
204 | Some(call_info) => { | 236 | Some(call_info) => { |
205 | let docs = match &call_info.signature.doc { | 237 | let docs = match &call_info.doc { |
206 | None => "".to_string(), | 238 | None => "".to_string(), |
207 | Some(docs) => format!("{}\n------\n", docs.as_str()), | 239 | Some(docs) => format!("{}\n------\n", docs.as_str()), |
208 | }; | 240 | }; |
209 | let params = call_info | 241 | let params = call_info |
210 | .signature | 242 | .parameter_labels() |
211 | .parameters | ||
212 | .iter() | ||
213 | .enumerate() | 243 | .enumerate() |
214 | .map(|(i, param)| { | 244 | .map(|(i, param)| { |
215 | if Some(i) == call_info.active_parameter { | 245 | if Some(i) == call_info.active_parameter { |
216 | format!("<{}>", param) | 246 | format!("<{}>", param) |
217 | } else { | 247 | } else { |
218 | param.clone() | 248 | param.to_string() |
219 | } | 249 | } |
220 | }) | 250 | }) |
221 | .collect::<Vec<_>>() | 251 | .collect::<Vec<_>>() |
@@ -296,10 +326,8 @@ fn foo<T, U: Copy + Display>(x: T, y: U) -> u32 | |||
296 | fn bar() { foo(<|>3, ); } | 326 | fn bar() { foo(<|>3, ); } |
297 | "#, | 327 | "#, |
298 | expect![[r#" | 328 | expect![[r#" |
299 | fn foo<T, U: Copy + Display>(x: T, y: U) -> u32 | 329 | fn foo(x: i32, y: {unknown}) -> u32 |
300 | where T: Copy + Display, | 330 | (<x: i32>, y: {unknown}) |
301 | U: Debug | ||
302 | (<x: T>, y: U) | ||
303 | "#]], | 331 | "#]], |
304 | ); | 332 | ); |
305 | } | 333 | } |
@@ -312,8 +340,7 @@ fn foo<T>() -> T where T: Copy + Display {} | |||
312 | fn bar() { foo(<|>); } | 340 | fn bar() { foo(<|>); } |
313 | "#, | 341 | "#, |
314 | expect![[r#" | 342 | expect![[r#" |
315 | fn foo<T>() -> T | 343 | fn foo() -> {unknown} |
316 | where T: Copy + Display | ||
317 | () | 344 | () |
318 | "#]], | 345 | "#]], |
319 | ); | 346 | ); |
@@ -323,11 +350,14 @@ fn bar() { foo(<|>); } | |||
323 | fn test_fn_signature_for_impl() { | 350 | fn test_fn_signature_for_impl() { |
324 | check( | 351 | check( |
325 | r#" | 352 | r#" |
326 | struct F; impl F { pub fn new() { F{}} } | 353 | struct F; |
327 | fn bar() {let _ : F = F::new(<|>);} | 354 | impl F { pub fn new() { } } |
355 | fn bar() { | ||
356 | let _ : F = F::new(<|>); | ||
357 | } | ||
328 | "#, | 358 | "#, |
329 | expect![[r#" | 359 | expect![[r#" |
330 | pub fn new() | 360 | fn new() |
331 | () | 361 | () |
332 | "#]], | 362 | "#]], |
333 | ); | 363 | ); |
@@ -346,8 +376,8 @@ fn bar() { | |||
346 | } | 376 | } |
347 | "#, | 377 | "#, |
348 | expect![[r#" | 378 | expect![[r#" |
349 | pub fn do_it(&self) | 379 | fn do_it(&self) |
350 | (&self) | 380 | () |
351 | "#]], | 381 | "#]], |
352 | ); | 382 | ); |
353 | } | 383 | } |
@@ -357,16 +387,33 @@ fn bar() { | |||
357 | check( | 387 | check( |
358 | r#" | 388 | r#" |
359 | struct S; | 389 | struct S; |
360 | impl S { pub fn do_it(&self, x: i32) {} } | 390 | impl S { |
391 | fn foo(&self, x: i32) {} | ||
392 | } | ||
361 | 393 | ||
362 | fn bar() { | 394 | fn main() { S.foo(<|>); } |
363 | let s: S = S; | 395 | "#, |
364 | s.do_it(<|>); | 396 | expect![[r#" |
397 | fn foo(&self, x: i32) | ||
398 | (<x: i32>) | ||
399 | "#]], | ||
400 | ); | ||
401 | } | ||
402 | |||
403 | #[test] | ||
404 | fn test_fn_signature_for_method_with_arg_as_assoc_fn() { | ||
405 | check( | ||
406 | r#" | ||
407 | struct S; | ||
408 | impl S { | ||
409 | fn foo(&self, x: i32) {} | ||
365 | } | 410 | } |
411 | |||
412 | fn main() { S::foo(<|>); } | ||
366 | "#, | 413 | "#, |
367 | expect![[r#" | 414 | expect![[r#" |
368 | pub fn do_it(&self, x: i32) | 415 | fn foo(self: &S, x: i32) |
369 | (&self, <x: i32>) | 416 | (<self: &S>, x: i32) |
370 | "#]], | 417 | "#]], |
371 | ); | 418 | ); |
372 | } | 419 | } |
@@ -425,7 +472,7 @@ pub fn do() { | |||
425 | assert_eq!(6, my_crate::add_one(5)); | 472 | assert_eq!(6, my_crate::add_one(5)); |
426 | ``` | 473 | ``` |
427 | ------ | 474 | ------ |
428 | pub fn add_one(x: i32) -> i32 | 475 | fn add_one(x: i32) -> i32 |
429 | (<x: i32>) | 476 | (<x: i32>) |
430 | "##]], | 477 | "##]], |
431 | ); | 478 | ); |
@@ -467,7 +514,7 @@ pub fn do_it() { | |||
467 | assert_eq!(6, my_crate::add_one(5)); | 514 | assert_eq!(6, my_crate::add_one(5)); |
468 | ``` | 515 | ``` |
469 | ------ | 516 | ------ |
470 | pub fn add_one(x: i32) -> i32 | 517 | fn add_one(x: i32) -> i32 |
471 | (<x: i32>) | 518 | (<x: i32>) |
472 | "##]], | 519 | "##]], |
473 | ); | 520 | ); |
@@ -505,8 +552,8 @@ pub fn foo(mut r: WriteHandler<()>) { | |||
505 | 552 | ||
506 | By default this method stops actor's `Context`. | 553 | By default this method stops actor's `Context`. |
507 | ------ | 554 | ------ |
508 | fn finished(&mut self, ctx: &mut Self::Context) | 555 | fn finished(&mut self, ctx: &mut {unknown}) |
509 | (&mut self, <ctx: &mut Self::Context>) | 556 | (<ctx: &mut {unknown}>) |
510 | "#]], | 557 | "#]], |
511 | ); | 558 | ); |
512 | } | 559 | } |
@@ -539,7 +586,7 @@ fn main() { | |||
539 | "#, | 586 | "#, |
540 | expect![[r#" | 587 | expect![[r#" |
541 | fn bar(&self, _: u32) | 588 | fn bar(&self, _: u32) |
542 | (&self, <_: u32>) | 589 | (<_: u32>) |
543 | "#]], | 590 | "#]], |
544 | ); | 591 | ); |
545 | } | 592 | } |
@@ -549,15 +596,15 @@ fn main() { | |||
549 | check( | 596 | check( |
550 | r#" | 597 | r#" |
551 | /// A cool tuple struct | 598 | /// A cool tuple struct |
552 | struct TS(u32, i32); | 599 | struct S(u32, i32); |
553 | fn main() { | 600 | fn main() { |
554 | let s = TS(0, <|>); | 601 | let s = S(0, <|>); |
555 | } | 602 | } |
556 | "#, | 603 | "#, |
557 | expect![[r#" | 604 | expect![[r#" |
558 | A cool tuple struct | 605 | A cool tuple struct |
559 | ------ | 606 | ------ |
560 | struct TS(u32, i32) -> TS | 607 | struct S(u32, i32) |
561 | (u32, <i32>) | 608 | (u32, <i32>) |
562 | "#]], | 609 | "#]], |
563 | ); | 610 | ); |
@@ -567,32 +614,19 @@ fn main() { | |||
567 | fn generic_struct() { | 614 | fn generic_struct() { |
568 | check( | 615 | check( |
569 | r#" | 616 | r#" |
570 | struct TS<T>(T); | 617 | struct S<T>(T); |
571 | fn main() { | 618 | fn main() { |
572 | let s = TS(<|>); | 619 | let s = S(<|>); |
573 | } | 620 | } |
574 | "#, | 621 | "#, |
575 | expect![[r#" | 622 | expect![[r#" |
576 | struct TS<T>(T) -> TS | 623 | struct S({unknown}) |
577 | (<T>) | 624 | (<{unknown}>) |
578 | "#]], | 625 | "#]], |
579 | ); | 626 | ); |
580 | } | 627 | } |
581 | 628 | ||
582 | #[test] | 629 | #[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() { | 630 | fn works_for_enum_variants() { |
597 | check( | 631 | check( |
598 | r#" | 632 | r#" |
@@ -612,27 +646,19 @@ fn main() { | |||
612 | expect![[r#" | 646 | expect![[r#" |
613 | A Variant | 647 | A Variant |
614 | ------ | 648 | ------ |
615 | E::A(0: i32) | 649 | enum E::A(i32) |
616 | (<0: i32>) | 650 | (<i32>) |
617 | "#]], | 651 | "#]], |
618 | ); | 652 | ); |
619 | } | 653 | } |
620 | 654 | ||
621 | #[test] | 655 | #[test] |
622 | fn cant_call_enum_records() { | 656 | fn cant_call_struct_record() { |
623 | check( | 657 | check( |
624 | r#" | 658 | r#" |
625 | enum E { | 659 | 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() { | 660 | fn main() { |
635 | let a = E::C(<|>); | 661 | let s = S(<|>); |
636 | } | 662 | } |
637 | "#, | 663 | "#, |
638 | expect![[""]], | 664 | expect![[""]], |
@@ -640,24 +666,23 @@ fn main() { | |||
640 | } | 666 | } |
641 | 667 | ||
642 | #[test] | 668 | #[test] |
643 | fn fn_signature_for_macro() { | 669 | fn cant_call_enum_record() { |
644 | check( | 670 | check( |
645 | r#" | 671 | r#" |
646 | /// empty macro | 672 | enum E { |
647 | macro_rules! foo { | 673 | /// A Variant |
648 | () => {} | 674 | A(i32), |
675 | /// Another | ||
676 | B, | ||
677 | /// And C | ||
678 | C { a: i32, b: i32 } | ||
649 | } | 679 | } |
650 | 680 | ||
651 | fn f() { | 681 | fn main() { |
652 | foo!(<|>); | 682 | let a = E::C(<|>); |
653 | } | 683 | } |
654 | "#, | 684 | "#, |
655 | expect![[r#" | 685 | expect![[""]], |
656 | empty macro | ||
657 | ------ | ||
658 | foo!() | ||
659 | () | ||
660 | "#]], | ||
661 | ); | 686 | ); |
662 | } | 687 | } |
663 | 688 | ||
diff --git a/crates/ra_ide/src/completion/complete_trait_impl.rs b/crates/ra_ide/src/completion/complete_trait_impl.rs index a610fd6d1..90f5b1c25 100644 --- a/crates/ra_ide/src/completion/complete_trait_impl.rs +++ b/crates/ra_ide/src/completion/complete_trait_impl.rs | |||
@@ -43,7 +43,7 @@ use crate::{ | |||
43 | completion::{ | 43 | completion::{ |
44 | CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, | 44 | CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, |
45 | }, | 45 | }, |
46 | display::FunctionSignature, | 46 | display::function_signature::FunctionSignature, |
47 | }; | 47 | }; |
48 | 48 | ||
49 | pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) { | 49 | pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) { |
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index 64349dcb8..e29b82017 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs | |||
@@ -11,7 +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::{const_label, macro_label, type_label, FunctionSignature}, | 14 | display::{const_label, function_signature::FunctionSignature, macro_label, type_label}, |
15 | CompletionScore, RootDatabase, | 15 | CompletionScore, RootDatabase, |
16 | }; | 16 | }; |
17 | 17 | ||
@@ -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.rs b/crates/ra_ide/src/display.rs index 70d2a2dd1..1ec946369 100644 --- a/crates/ra_ide/src/display.rs +++ b/crates/ra_ide/src/display.rs | |||
@@ -1,9 +1,8 @@ | |||
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 | ||
4 | mod function_signature; | 4 | pub(crate) mod function_signature; |
5 | mod navigation_target; | 5 | mod navigation_target; |
6 | mod structure; | ||
7 | mod short_label; | 6 | mod short_label; |
8 | 7 | ||
9 | use ra_syntax::{ | 8 | use ra_syntax::{ |
@@ -11,15 +10,13 @@ use ra_syntax::{ | |||
11 | SyntaxKind::{ATTR, COMMENT}, | 10 | SyntaxKind::{ATTR, COMMENT}, |
12 | }; | 11 | }; |
13 | 12 | ||
14 | pub use function_signature::FunctionSignature; | ||
15 | pub use navigation_target::NavigationTarget; | ||
16 | pub use structure::{file_structure, StructureNode}; | ||
17 | |||
18 | pub(crate) use navigation_target::{ToNav, TryToNav}; | 13 | pub(crate) use navigation_target::{ToNav, TryToNav}; |
19 | pub(crate) use short_label::ShortLabel; | 14 | pub(crate) use short_label::ShortLabel; |
20 | 15 | ||
16 | pub use navigation_target::NavigationTarget; | ||
17 | |||
21 | pub(crate) fn function_label(node: &ast::FnDef) -> String { | 18 | pub(crate) fn function_label(node: &ast::FnDef) -> String { |
22 | FunctionSignature::from(node).to_string() | 19 | function_signature::FunctionSignature::from(node).to_string() |
23 | } | 20 | } |
24 | 21 | ||
25 | pub(crate) fn const_label(node: &ast::ConstDef) -> String { | 22 | pub(crate) fn const_label(node: &ast::ConstDef) -> String { |
diff --git a/crates/ra_ide/src/display/function_signature.rs b/crates/ra_ide/src/display/function_signature.rs index 1d39544d3..9b7220d1f 100644 --- a/crates/ra_ide/src/display/function_signature.rs +++ b/crates/ra_ide/src/display/function_signature.rs | |||
@@ -15,49 +15,48 @@ use stdx::{split_delim, SepBy}; | |||
15 | use crate::display::{generic_parameters, where_predicates}; | 15 | use crate::display::{generic_parameters, where_predicates}; |
16 | 16 | ||
17 | #[derive(Debug)] | 17 | #[derive(Debug)] |
18 | pub enum CallableKind { | 18 | pub(crate) enum CallableKind { |
19 | Function, | 19 | Function, |
20 | StructConstructor, | 20 | StructConstructor, |
21 | VariantConstructor, | 21 | VariantConstructor, |
22 | Macro, | ||
23 | } | 22 | } |
24 | 23 | ||
25 | /// Contains information about a function signature | 24 | /// Contains information about a function signature |
26 | #[derive(Debug)] | 25 | #[derive(Debug)] |
27 | pub struct FunctionSignature { | 26 | pub(crate) struct FunctionSignature { |
28 | pub kind: CallableKind, | 27 | pub(crate) kind: CallableKind, |
29 | /// Optional visibility | 28 | /// Optional visibility |
30 | pub visibility: Option<String>, | 29 | pub(crate) visibility: Option<String>, |
31 | /// Qualifiers like `async`, `unsafe`, ... | 30 | /// Qualifiers like `async`, `unsafe`, ... |
32 | pub qualifier: FunctionQualifier, | 31 | pub(crate) qualifier: FunctionQualifier, |
33 | /// Name of the function | 32 | /// Name of the function |
34 | pub name: Option<String>, | 33 | pub(crate) name: Option<String>, |
35 | /// Documentation for the function | 34 | /// Documentation for the function |
36 | pub doc: Option<Documentation>, | 35 | pub(crate) doc: Option<Documentation>, |
37 | /// Generic parameters | 36 | /// Generic parameters |
38 | pub generic_parameters: Vec<String>, | 37 | pub(crate) generic_parameters: Vec<String>, |
39 | /// Parameters of the function | 38 | /// Parameters of the function |
40 | pub parameters: Vec<String>, | 39 | pub(crate) parameters: Vec<String>, |
41 | /// Parameter names of the function | 40 | /// Parameter names of the function |
42 | pub parameter_names: Vec<String>, | 41 | pub(crate) parameter_names: Vec<String>, |
43 | /// Parameter types of the function | 42 | /// Parameter types of the function |
44 | pub parameter_types: Vec<String>, | 43 | pub(crate) parameter_types: Vec<String>, |
45 | /// Optional return type | 44 | /// Optional return type |
46 | pub ret_type: Option<String>, | 45 | pub(crate) ret_type: Option<String>, |
47 | /// Where predicates | 46 | /// Where predicates |
48 | pub where_predicates: Vec<String>, | 47 | pub(crate) where_predicates: Vec<String>, |
49 | /// Self param presence | 48 | /// Self param presence |
50 | pub has_self_param: bool, | 49 | pub(crate) has_self_param: bool, |
51 | } | 50 | } |
52 | 51 | ||
53 | #[derive(Debug, Default)] | 52 | #[derive(Debug, Default)] |
54 | pub struct FunctionQualifier { | 53 | pub(crate) struct FunctionQualifier { |
55 | // `async` and `const` are mutually exclusive. Do we need to enforcing it here? | 54 | // `async` and `const` are mutually exclusive. Do we need to enforcing it here? |
56 | pub is_async: bool, | 55 | pub(crate) is_async: bool, |
57 | pub is_const: bool, | 56 | pub(crate) is_const: bool, |
58 | pub is_unsafe: bool, | 57 | pub(crate) is_unsafe: bool, |
59 | /// The string `extern ".."` | 58 | /// The string `extern ".."` |
60 | pub extern_abi: Option<String>, | 59 | pub(crate) extern_abi: Option<String>, |
61 | } | 60 | } |
62 | 61 | ||
63 | impl FunctionSignature { | 62 | impl FunctionSignature { |
@@ -149,27 +148,6 @@ impl FunctionSignature { | |||
149 | has_self_param: false, | 148 | has_self_param: false, |
150 | }) | 149 | }) |
151 | } | 150 | } |
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 | } | 151 | } |
174 | 152 | ||
175 | impl From<&'_ ast::FnDef> for FunctionSignature { | 153 | impl From<&'_ ast::FnDef> for FunctionSignature { |
@@ -298,7 +276,6 @@ impl Display for FunctionSignature { | |||
298 | CallableKind::Function => write!(f, "fn {}", name)?, | 276 | CallableKind::Function => write!(f, "fn {}", name)?, |
299 | CallableKind::StructConstructor => write!(f, "struct {}", name)?, | 277 | CallableKind::StructConstructor => write!(f, "struct {}", name)?, |
300 | CallableKind::VariantConstructor => write!(f, "{}", name)?, | 278 | CallableKind::VariantConstructor => write!(f, "{}", name)?, |
301 | CallableKind::Macro => write!(f, "{}!", name)?, | ||
302 | } | 279 | } |
303 | } | 280 | } |
304 | 281 | ||
diff --git a/crates/ra_ide/src/display/structure.rs b/crates/ra_ide/src/file_structure.rs index 1f6a3febf..1f6a3febf 100644 --- a/crates/ra_ide/src/display/structure.rs +++ b/crates/ra_ide/src/file_structure.rs | |||
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 3cbae8a45..ae5695f61 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs | |||
@@ -5,10 +5,10 @@ use ra_syntax::{ | |||
5 | ast::{self, ArgListOwner, AstNode, TypeAscriptionOwner}, | 5 | ast::{self, ArgListOwner, AstNode, TypeAscriptionOwner}, |
6 | match_ast, Direction, NodeOrToken, SmolStr, SyntaxKind, TextRange, T, | 6 | match_ast, Direction, NodeOrToken, SmolStr, SyntaxKind, TextRange, T, |
7 | }; | 7 | }; |
8 | |||
9 | use crate::{FileId, FunctionSignature}; | ||
10 | use stdx::to_lower_snake_case; | 8 | use stdx::to_lower_snake_case; |
11 | 9 | ||
10 | use crate::{display::function_signature::FunctionSignature, FileId}; | ||
11 | |||
12 | #[derive(Clone, Debug, PartialEq, Eq)] | 12 | #[derive(Clone, Debug, PartialEq, Eq)] |
13 | pub struct InlayHintsConfig { | 13 | pub struct InlayHintsConfig { |
14 | pub type_hints: bool, | 14 | pub type_hints: bool, |
@@ -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 | } |
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 5d1f64e19..d3b20f371 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs | |||
@@ -19,29 +19,31 @@ pub mod mock_analysis; | |||
19 | 19 | ||
20 | mod markup; | 20 | mod markup; |
21 | mod prime_caches; | 21 | mod prime_caches; |
22 | mod status; | 22 | mod display; |
23 | |||
24 | mod call_hierarchy; | ||
25 | mod call_info; | ||
23 | mod completion; | 26 | mod completion; |
24 | mod runnables; | 27 | mod diagnostics; |
28 | mod expand_macro; | ||
29 | mod extend_selection; | ||
30 | mod file_structure; | ||
31 | mod folding_ranges; | ||
25 | mod goto_definition; | 32 | mod goto_definition; |
26 | mod goto_type_definition; | ||
27 | mod goto_implementation; | 33 | mod goto_implementation; |
28 | mod extend_selection; | 34 | mod goto_type_definition; |
29 | mod hover; | 35 | mod hover; |
30 | mod call_hierarchy; | 36 | mod inlay_hints; |
31 | mod call_info; | 37 | mod join_lines; |
32 | mod syntax_highlighting; | 38 | mod matching_brace; |
33 | mod parent_module; | 39 | mod parent_module; |
34 | mod references; | 40 | mod references; |
35 | mod diagnostics; | 41 | mod runnables; |
42 | mod ssr; | ||
43 | mod status; | ||
44 | mod syntax_highlighting; | ||
36 | mod syntax_tree; | 45 | mod syntax_tree; |
37 | mod folding_ranges; | ||
38 | mod join_lines; | ||
39 | mod typing; | 46 | mod typing; |
40 | mod matching_brace; | ||
41 | mod display; | ||
42 | mod inlay_hints; | ||
43 | mod expand_macro; | ||
44 | mod ssr; | ||
45 | 47 | ||
46 | use std::sync::Arc; | 48 | use std::sync::Arc; |
47 | 49 | ||
@@ -65,8 +67,9 @@ pub use crate::{ | |||
65 | CompletionConfig, CompletionItem, CompletionItemKind, CompletionScore, InsertTextFormat, | 67 | CompletionConfig, CompletionItem, CompletionItemKind, CompletionScore, InsertTextFormat, |
66 | }, | 68 | }, |
67 | diagnostics::Severity, | 69 | diagnostics::Severity, |
68 | display::{file_structure, FunctionSignature, NavigationTarget, StructureNode}, | 70 | display::NavigationTarget, |
69 | expand_macro::ExpandedMacro, | 71 | expand_macro::ExpandedMacro, |
72 | file_structure::StructureNode, | ||
70 | folding_ranges::{Fold, FoldKind}, | 73 | folding_ranges::{Fold, FoldKind}, |
71 | hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult}, | 74 | hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult}, |
72 | inlay_hints::{InlayHint, InlayHintsConfig, InlayKind}, | 75 | inlay_hints::{InlayHint, InlayHintsConfig, InlayKind}, |
@@ -323,7 +326,7 @@ impl Analysis { | |||
323 | /// Returns a tree representation of symbols in the file. Useful to draw a | 326 | /// Returns a tree representation of symbols in the file. Useful to draw a |
324 | /// file outline. | 327 | /// file outline. |
325 | pub fn file_structure(&self, file_id: FileId) -> Cancelable<Vec<StructureNode>> { | 328 | pub fn file_structure(&self, file_id: FileId) -> Cancelable<Vec<StructureNode>> { |
326 | self.with_db(|db| file_structure(&db.parse(file_id).tree())) | 329 | self.with_db(|db| file_structure::file_structure(&db.parse(file_id).tree())) |
327 | } | 330 | } |
328 | 331 | ||
329 | /// Returns a list of the places in the file where type hints can be displayed. | 332 | /// Returns a list of the places in the file where type hints can be displayed. |