diff options
Diffstat (limited to 'crates/ra_ide/src/display')
-rw-r--r-- | crates/ra_ide/src/display/function_signature.rs | 23 | ||||
-rw-r--r-- | crates/ra_ide/src/display/navigation_target.rs | 85 | ||||
-rw-r--r-- | crates/ra_ide/src/display/short_label.rs | 6 | ||||
-rw-r--r-- | crates/ra_ide/src/display/structure.rs | 19 |
4 files changed, 73 insertions, 60 deletions
diff --git a/crates/ra_ide/src/display/function_signature.rs b/crates/ra_ide/src/display/function_signature.rs index db3907fe6..9572debd8 100644 --- a/crates/ra_ide/src/display/function_signature.rs +++ b/crates/ra_ide/src/display/function_signature.rs | |||
@@ -1,5 +1,7 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | // FIXME: this modules relies on strings and AST way too much, and it should be | ||
4 | // rewritten (matklad 2020-05-07) | ||
3 | use std::{ | 5 | use std::{ |
4 | convert::From, | 6 | convert::From, |
5 | fmt::{self, Display}, | 7 | fmt::{self, Display}, |
@@ -82,8 +84,8 @@ impl FunctionSignature { | |||
82 | let ty = field.signature_ty(db); | 84 | let ty = field.signature_ty(db); |
83 | let raw_param = format!("{}", ty.display(db)); | 85 | let raw_param = format!("{}", ty.display(db)); |
84 | 86 | ||
85 | if let Some(param_type) = raw_param.split(':').nth(1) { | 87 | if let Some(param_type) = raw_param.split(':').nth(1).and_then(|it| it.get(1..)) { |
86 | parameter_types.push(param_type[1..].to_string()); | 88 | parameter_types.push(param_type.to_string()); |
87 | } else { | 89 | } else { |
88 | // useful when you have tuple struct | 90 | // useful when you have tuple struct |
89 | parameter_types.push(raw_param.clone()); | 91 | parameter_types.push(raw_param.clone()); |
@@ -127,8 +129,8 @@ impl FunctionSignature { | |||
127 | for field in variant.fields(db).into_iter() { | 129 | for field in variant.fields(db).into_iter() { |
128 | let ty = field.signature_ty(db); | 130 | let ty = field.signature_ty(db); |
129 | let raw_param = format!("{}", ty.display(db)); | 131 | let raw_param = format!("{}", ty.display(db)); |
130 | if let Some(param_type) = raw_param.split(':').nth(1) { | 132 | if let Some(param_type) = raw_param.split(':').nth(1).and_then(|it| it.get(1..)) { |
131 | parameter_types.push(param_type[1..].to_string()); | 133 | parameter_types.push(param_type.to_string()); |
132 | } else { | 134 | } else { |
133 | // The unwrap_or_else is useful when you have tuple | 135 | // The unwrap_or_else is useful when you have tuple |
134 | parameter_types.push(raw_param); | 136 | parameter_types.push(raw_param); |
@@ -195,14 +197,23 @@ impl From<&'_ ast::FnDef> for FunctionSignature { | |||
195 | let raw_param = self_param.syntax().text().to_string(); | 197 | let raw_param = self_param.syntax().text().to_string(); |
196 | 198 | ||
197 | res_types.push( | 199 | res_types.push( |
198 | raw_param.split(':').nth(1).unwrap_or_else(|| " Self")[1..].to_string(), | 200 | raw_param |
201 | .split(':') | ||
202 | .nth(1) | ||
203 | .and_then(|it| it.get(1..)) | ||
204 | .unwrap_or_else(|| "Self") | ||
205 | .to_string(), | ||
199 | ); | 206 | ); |
200 | res.push(raw_param); | 207 | res.push(raw_param); |
201 | } | 208 | } |
202 | 209 | ||
203 | res.extend(param_list.params().map(|param| param.syntax().text().to_string())); | 210 | res.extend(param_list.params().map(|param| param.syntax().text().to_string())); |
204 | res_types.extend(param_list.params().map(|param| { | 211 | res_types.extend(param_list.params().map(|param| { |
205 | param.syntax().text().to_string().split(':').nth(1).unwrap()[1..].to_string() | 212 | let param_text = param.syntax().text().to_string(); |
213 | match param_text.split(':').nth(1).and_then(|it| it.get(1..)) { | ||
214 | Some(it) => it.to_string(), | ||
215 | None => param_text, | ||
216 | } | ||
206 | })); | 217 | })); |
207 | } | 218 | } |
208 | (has_self_param, res, res_types) | 219 | (has_self_param, res, res_types) |
diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs index 914a8b471..c7bb1e69f 100644 --- a/crates/ra_ide/src/display/navigation_target.rs +++ b/crates/ra_ide/src/display/navigation_target.rs | |||
@@ -11,7 +11,7 @@ use ra_syntax::{ | |||
11 | TextRange, | 11 | TextRange, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | use crate::FileSymbol; | 14 | use crate::{FileRange, FileSymbol}; |
15 | 15 | ||
16 | use super::short_label::ShortLabel; | 16 | use super::short_label::ShortLabel; |
17 | 17 | ||
@@ -22,10 +22,11 @@ use super::short_label::ShortLabel; | |||
22 | /// code, like a function or a struct, but this is not strictly required. | 22 | /// code, like a function or a struct, but this is not strictly required. |
23 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 23 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
24 | pub struct NavigationTarget { | 24 | pub struct NavigationTarget { |
25 | // FIXME: use FileRange? | ||
25 | file_id: FileId, | 26 | file_id: FileId, |
27 | full_range: TextRange, | ||
26 | name: SmolStr, | 28 | name: SmolStr, |
27 | kind: SyntaxKind, | 29 | kind: SyntaxKind, |
28 | full_range: TextRange, | ||
29 | focus_range: Option<TextRange>, | 30 | focus_range: Option<TextRange>, |
30 | container_name: Option<SmolStr>, | 31 | container_name: Option<SmolStr>, |
31 | description: Option<String>, | 32 | description: Option<String>, |
@@ -63,6 +64,10 @@ impl NavigationTarget { | |||
63 | self.file_id | 64 | self.file_id |
64 | } | 65 | } |
65 | 66 | ||
67 | pub fn file_range(&self) -> FileRange { | ||
68 | FileRange { file_id: self.file_id, range: self.full_range } | ||
69 | } | ||
70 | |||
66 | pub fn full_range(&self) -> TextRange { | 71 | pub fn full_range(&self) -> TextRange { |
67 | self.full_range | 72 | self.full_range |
68 | } | 73 | } |
@@ -87,15 +92,16 @@ impl NavigationTarget { | |||
87 | let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default(); | 92 | let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default(); |
88 | if let Some(src) = module.declaration_source(db) { | 93 | if let Some(src) = module.declaration_source(db) { |
89 | let frange = original_range(db, src.as_ref().map(|it| it.syntax())); | 94 | let frange = original_range(db, src.as_ref().map(|it| it.syntax())); |
90 | return NavigationTarget::from_syntax( | 95 | let mut res = NavigationTarget::from_syntax( |
91 | frange.file_id, | 96 | frange.file_id, |
92 | name, | 97 | name, |
93 | None, | 98 | None, |
94 | frange.range, | 99 | frange.range, |
95 | src.value.syntax().kind(), | 100 | src.value.syntax().kind(), |
96 | src.value.doc_comment_text(), | ||
97 | src.value.short_label(), | ||
98 | ); | 101 | ); |
102 | res.docs = src.value.doc_comment_text(); | ||
103 | res.description = src.value.short_label(); | ||
104 | return res; | ||
99 | } | 105 | } |
100 | module.to_nav(db) | 106 | module.to_nav(db) |
101 | } | 107 | } |
@@ -125,11 +131,9 @@ impl NavigationTarget { | |||
125 | } | 131 | } |
126 | 132 | ||
127 | /// Allows `NavigationTarget` to be created from a `NameOwner` | 133 | /// Allows `NavigationTarget` to be created from a `NameOwner` |
128 | fn from_named( | 134 | pub(crate) fn from_named( |
129 | db: &RootDatabase, | 135 | db: &RootDatabase, |
130 | node: InFile<&dyn ast::NameOwner>, | 136 | node: InFile<&dyn ast::NameOwner>, |
131 | docs: Option<String>, | ||
132 | description: Option<String>, | ||
133 | ) -> NavigationTarget { | 137 | ) -> NavigationTarget { |
134 | //FIXME: use `_` instead of empty string | 138 | //FIXME: use `_` instead of empty string |
135 | let name = node.value.name().map(|it| it.text().clone()).unwrap_or_default(); | 139 | let name = node.value.name().map(|it| it.text().clone()).unwrap_or_default(); |
@@ -143,8 +147,6 @@ impl NavigationTarget { | |||
143 | focus_range, | 147 | focus_range, |
144 | frange.range, | 148 | frange.range, |
145 | node.value.syntax().kind(), | 149 | node.value.syntax().kind(), |
146 | docs, | ||
147 | description, | ||
148 | ) | 150 | ) |
149 | } | 151 | } |
150 | 152 | ||
@@ -154,8 +156,6 @@ impl NavigationTarget { | |||
154 | focus_range: Option<TextRange>, | 156 | focus_range: Option<TextRange>, |
155 | full_range: TextRange, | 157 | full_range: TextRange, |
156 | kind: SyntaxKind, | 158 | kind: SyntaxKind, |
157 | docs: Option<String>, | ||
158 | description: Option<String>, | ||
159 | ) -> NavigationTarget { | 159 | ) -> NavigationTarget { |
160 | NavigationTarget { | 160 | NavigationTarget { |
161 | file_id, | 161 | file_id, |
@@ -164,8 +164,8 @@ impl NavigationTarget { | |||
164 | full_range, | 164 | full_range, |
165 | focus_range, | 165 | focus_range, |
166 | container_name: None, | 166 | container_name: None, |
167 | description, | 167 | description: None, |
168 | docs, | 168 | docs: None, |
169 | } | 169 | } |
170 | } | 170 | } |
171 | } | 171 | } |
@@ -233,12 +233,11 @@ where | |||
233 | { | 233 | { |
234 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 234 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { |
235 | let src = self.source(db); | 235 | let src = self.source(db); |
236 | NavigationTarget::from_named( | 236 | let mut res = |
237 | db, | 237 | NavigationTarget::from_named(db, src.as_ref().map(|it| it as &dyn ast::NameOwner)); |
238 | src.as_ref().map(|it| it as &dyn ast::NameOwner), | 238 | res.docs = src.value.doc_comment_text(); |
239 | src.value.doc_comment_text(), | 239 | res.description = src.value.short_label(); |
240 | src.value.short_label(), | 240 | res |
241 | ) | ||
242 | } | 241 | } |
243 | } | 242 | } |
244 | 243 | ||
@@ -253,15 +252,7 @@ impl ToNav for hir::Module { | |||
253 | } | 252 | } |
254 | }; | 253 | }; |
255 | let frange = original_range(db, src.with_value(syntax)); | 254 | let frange = original_range(db, src.with_value(syntax)); |
256 | NavigationTarget::from_syntax( | 255 | NavigationTarget::from_syntax(frange.file_id, name, focus, frange.range, syntax.kind()) |
257 | frange.file_id, | ||
258 | name, | ||
259 | focus, | ||
260 | frange.range, | ||
261 | syntax.kind(), | ||
262 | None, | ||
263 | None, | ||
264 | ) | ||
265 | } | 256 | } |
266 | } | 257 | } |
267 | 258 | ||
@@ -280,8 +271,6 @@ impl ToNav for hir::ImplDef { | |||
280 | None, | 271 | None, |
281 | frange.range, | 272 | frange.range, |
282 | src.value.syntax().kind(), | 273 | src.value.syntax().kind(), |
283 | None, | ||
284 | None, | ||
285 | ) | 274 | ) |
286 | } | 275 | } |
287 | } | 276 | } |
@@ -291,12 +280,12 @@ impl ToNav for hir::Field { | |||
291 | let src = self.source(db); | 280 | let src = self.source(db); |
292 | 281 | ||
293 | match &src.value { | 282 | match &src.value { |
294 | FieldSource::Named(it) => NavigationTarget::from_named( | 283 | FieldSource::Named(it) => { |
295 | db, | 284 | let mut res = NavigationTarget::from_named(db, src.with_value(it)); |
296 | src.with_value(it), | 285 | res.docs = it.doc_comment_text(); |
297 | it.doc_comment_text(), | 286 | res.description = it.short_label(); |
298 | it.short_label(), | 287 | res |
299 | ), | 288 | } |
300 | FieldSource::Pos(it) => { | 289 | FieldSource::Pos(it) => { |
301 | let frange = original_range(db, src.with_value(it.syntax())); | 290 | let frange = original_range(db, src.with_value(it.syntax())); |
302 | NavigationTarget::from_syntax( | 291 | NavigationTarget::from_syntax( |
@@ -305,8 +294,6 @@ impl ToNav for hir::Field { | |||
305 | None, | 294 | None, |
306 | frange.range, | 295 | frange.range, |
307 | it.syntax().kind(), | 296 | it.syntax().kind(), |
308 | None, | ||
309 | None, | ||
310 | ) | 297 | ) |
311 | } | 298 | } |
312 | } | 299 | } |
@@ -317,12 +304,10 @@ impl ToNav for hir::MacroDef { | |||
317 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 304 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { |
318 | let src = self.source(db); | 305 | let src = self.source(db); |
319 | log::debug!("nav target {:#?}", src.value.syntax()); | 306 | log::debug!("nav target {:#?}", src.value.syntax()); |
320 | NavigationTarget::from_named( | 307 | let mut res = |
321 | db, | 308 | NavigationTarget::from_named(db, src.as_ref().map(|it| it as &dyn ast::NameOwner)); |
322 | src.as_ref().map(|it| it as &dyn ast::NameOwner), | 309 | res.docs = src.value.doc_comment_text(); |
323 | src.value.doc_comment_text(), | 310 | res |
324 | None, | ||
325 | ) | ||
326 | } | 311 | } |
327 | } | 312 | } |
328 | 313 | ||
@@ -376,16 +361,20 @@ impl ToNav for hir::Local { | |||
376 | impl ToNav for hir::TypeParam { | 361 | impl ToNav for hir::TypeParam { |
377 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 362 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { |
378 | let src = self.source(db); | 363 | let src = self.source(db); |
379 | let range = match src.value { | 364 | let full_range = match &src.value { |
380 | Either::Left(it) => it.syntax().text_range(), | 365 | Either::Left(it) => it.syntax().text_range(), |
381 | Either::Right(it) => it.syntax().text_range(), | 366 | Either::Right(it) => it.syntax().text_range(), |
382 | }; | 367 | }; |
368 | let focus_range = match &src.value { | ||
369 | Either::Left(_) => None, | ||
370 | Either::Right(it) => it.name().map(|it| it.syntax().text_range()), | ||
371 | }; | ||
383 | NavigationTarget { | 372 | NavigationTarget { |
384 | file_id: src.file_id.original_file(db), | 373 | file_id: src.file_id.original_file(db), |
385 | name: self.name(db).to_string().into(), | 374 | name: self.name(db).to_string().into(), |
386 | kind: TYPE_PARAM, | 375 | kind: TYPE_PARAM, |
387 | full_range: range, | 376 | full_range, |
388 | focus_range: None, | 377 | focus_range, |
389 | container_name: None, | 378 | container_name: None, |
390 | description: None, | 379 | description: None, |
391 | docs: None, | 380 | docs: None, |
diff --git a/crates/ra_ide/src/display/short_label.rs b/crates/ra_ide/src/display/short_label.rs index 4b081bf6c..d37260e96 100644 --- a/crates/ra_ide/src/display/short_label.rs +++ b/crates/ra_ide/src/display/short_label.rs | |||
@@ -33,7 +33,11 @@ impl ShortLabel for ast::EnumDef { | |||
33 | 33 | ||
34 | impl ShortLabel for ast::TraitDef { | 34 | impl ShortLabel for ast::TraitDef { |
35 | fn short_label(&self) -> Option<String> { | 35 | fn short_label(&self) -> Option<String> { |
36 | short_label_from_node(self, "trait ") | 36 | if self.unsafe_token().is_some() { |
37 | short_label_from_node(self, "unsafe trait ") | ||
38 | } else { | ||
39 | short_label_from_node(self, "trait ") | ||
40 | } | ||
37 | } | 41 | } |
38 | } | 42 | } |
39 | 43 | ||
diff --git a/crates/ra_ide/src/display/structure.rs b/crates/ra_ide/src/display/structure.rs index 967eee5d2..aad5a8e4d 100644 --- a/crates/ra_ide/src/display/structure.rs +++ b/crates/ra_ide/src/display/structure.rs | |||
@@ -1,10 +1,6 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
3 | use crate::TextRange; | ||
4 | |||
5 | use ra_syntax::{ | 1 | use ra_syntax::{ |
6 | ast::{self, AttrsOwner, NameOwner, TypeAscriptionOwner, TypeParamsOwner}, | 2 | ast::{self, AttrsOwner, NameOwner, TypeAscriptionOwner, TypeParamsOwner}, |
7 | match_ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, WalkEvent, | 3 | match_ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, TextRange, WalkEvent, |
8 | }; | 4 | }; |
9 | 5 | ||
10 | #[derive(Debug, Clone)] | 6 | #[derive(Debug, Clone)] |
@@ -18,6 +14,19 @@ pub struct StructureNode { | |||
18 | pub deprecated: bool, | 14 | pub deprecated: bool, |
19 | } | 15 | } |
20 | 16 | ||
17 | // Feature: File Structure | ||
18 | // | ||
19 | // Provides a tree of the symbols defined in the file. Can be used to | ||
20 | // | ||
21 | // * fuzzy search symbol in a file (super useful) | ||
22 | // * draw breadcrumbs to describe the context around the cursor | ||
23 | // * draw outline of the file | ||
24 | // | ||
25 | // |=== | ||
26 | // | Editor | Shortcut | ||
27 | // | ||
28 | // | VS Code | kbd:[Ctrl+Shift+O] | ||
29 | // |=== | ||
21 | pub fn file_structure(file: &SourceFile) -> Vec<StructureNode> { | 30 | pub fn file_structure(file: &SourceFile) -> Vec<StructureNode> { |
22 | let mut res = Vec::new(); | 31 | let mut res = Vec::new(); |
23 | let mut stack = Vec::new(); | 32 | let mut stack = Vec::new(); |