aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api/src')
-rw-r--r--crates/ra_ide_api/src/display.rs5
-rw-r--r--crates/ra_ide_api/src/display/navigation_target.rs149
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs4
-rw-r--r--crates/ra_ide_api/src/hover.rs6
-rw-r--r--crates/ra_ide_api/src/lib.rs2
5 files changed, 86 insertions, 80 deletions
diff --git a/crates/ra_ide_api/src/display.rs b/crates/ra_ide_api/src/display.rs
index 1b06abf94..0eef11464 100644
--- a/crates/ra_ide_api/src/display.rs
+++ b/crates/ra_ide_api/src/display.rs
@@ -5,7 +5,6 @@ mod function_signature;
5mod navigation_target; 5mod navigation_target;
6mod structure; 6mod structure;
7 7
8use crate::db::RootDatabase;
9use ra_syntax::{ast::{self, AstNode, TypeParamsOwner}, SyntaxKind::{ATTR, COMMENT}}; 8use ra_syntax::{ast::{self, AstNode, TypeParamsOwner}, SyntaxKind::{ATTR, COMMENT}};
10 9
11pub use navigation_target::NavigationTarget; 10pub use navigation_target::NavigationTarget;
@@ -73,8 +72,8 @@ where
73 72
74// FIXME: this should not really use navigation target. Rather, approximately 73// FIXME: this should not really use navigation target. Rather, approximately
75// resolved symbol should return a `DefId`. 74// resolved symbol should return a `DefId`.
76pub(crate) fn doc_text_for(db: &RootDatabase, nav: NavigationTarget) -> Option<String> { 75pub(crate) fn doc_text_for(nav: NavigationTarget) -> Option<String> {
77 match (nav.description(db), nav.docs(db)) { 76 match (nav.description, nav.docs) {
78 (Some(desc), docs) => Some(rust_code_markup_with_doc(desc, docs)), 77 (Some(desc), docs) => Some(rust_code_markup_with_doc(desc, docs)),
79 (None, Some(docs)) => Some(docs), 78 (None, Some(docs)) => Some(docs),
80 _ => None, 79 _ => None,
diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs
index 45002d098..f8a7bd3ad 100644
--- a/crates/ra_ide_api/src/display/navigation_target.rs
+++ b/crates/ra_ide_api/src/display/navigation_target.rs
@@ -1,6 +1,6 @@
1use ra_db::{FileId, SourceDatabase}; 1use ra_db::{FileId, SourceDatabase};
2use ra_syntax::{ 2use ra_syntax::{
3 SyntaxNode, AstNode, SmolStr, TextRange, TreeArc, AstPtr, 3 SyntaxNode, AstNode, SmolStr, TextRange, AstPtr,
4 SyntaxKind::{self, NAME}, 4 SyntaxKind::{self, NAME},
5 ast::{self, NameOwner, VisibilityOwner, TypeAscriptionOwner}, 5 ast::{self, NameOwner, VisibilityOwner, TypeAscriptionOwner},
6 algo::visit::{visitor, Visitor}, 6 algo::visit::{visitor, Visitor},
@@ -22,6 +22,9 @@ pub struct NavigationTarget {
22 full_range: TextRange, 22 full_range: TextRange,
23 focus_range: Option<TextRange>, 23 focus_range: Option<TextRange>,
24 container_name: Option<SmolStr>, 24 container_name: Option<SmolStr>,
25
26 pub(crate) description: Option<String>,
27 pub(crate) docs: Option<String>,
25} 28}
26 29
27impl NavigationTarget { 30impl NavigationTarget {
@@ -63,7 +66,10 @@ impl NavigationTarget {
63 NavigationTarget::from_named(file_id, pat) 66 NavigationTarget::from_named(file_id, pat)
64 } 67 }
65 68
66 pub(crate) fn from_symbol(symbol: FileSymbol) -> NavigationTarget { 69 pub(crate) fn from_symbol(db: &RootDatabase, symbol: FileSymbol) -> NavigationTarget {
70 let file = db.parse(symbol.file_id).tree;
71 let node = symbol.ptr.to_node(file.syntax()).to_owned();
72
67 NavigationTarget { 73 NavigationTarget {
68 file_id: symbol.file_id, 74 file_id: symbol.file_id,
69 name: symbol.name.clone(), 75 name: symbol.name.clone(),
@@ -71,6 +77,8 @@ impl NavigationTarget {
71 full_range: symbol.ptr.range(), 77 full_range: symbol.ptr.range(),
72 focus_range: symbol.name_range, 78 focus_range: symbol.name_range,
73 container_name: symbol.container_name.clone(), 79 container_name: symbol.container_name.clone(),
80 description: description_inner(&node),
81 docs: docs_inner(&node),
74 } 82 }
75 } 83 }
76 84
@@ -84,6 +92,8 @@ impl NavigationTarget {
84 ast::PatKind::BindPat(pat) => return NavigationTarget::from_bind_pat(file_id, &pat), 92 ast::PatKind::BindPat(pat) => return NavigationTarget::from_bind_pat(file_id, &pat),
85 _ => ("_".into(), pat.syntax_node_ptr().range()), 93 _ => ("_".into(), pat.syntax_node_ptr().range()),
86 }; 94 };
95 let node = pat.to_node(file.syntax()).syntax().to_owned();
96
87 NavigationTarget { 97 NavigationTarget {
88 file_id, 98 file_id,
89 name, 99 name,
@@ -91,14 +101,20 @@ impl NavigationTarget {
91 focus_range: None, 101 focus_range: None,
92 kind: NAME, 102 kind: NAME,
93 container_name: None, 103 container_name: None,
104 description: description_inner(&node),
105 docs: docs_inner(&node),
94 } 106 }
95 } 107 }
96 108
97 pub(crate) fn from_self_param( 109 pub(crate) fn from_self_param(
110 db: &RootDatabase,
98 file_id: FileId, 111 file_id: FileId,
99 par: AstPtr<ast::SelfParam>, 112 par: AstPtr<ast::SelfParam>,
100 ) -> NavigationTarget { 113 ) -> NavigationTarget {
101 let (name, full_range) = ("self".into(), par.syntax_node_ptr().range()); 114 let (name, full_range) = ("self".into(), par.syntax_node_ptr().range());
115 let file = db.parse(file_id).tree;
116 let node = par.to_node(file.syntax()).syntax().to_owned();
117
102 NavigationTarget { 118 NavigationTarget {
103 file_id, 119 file_id,
104 name, 120 name,
@@ -106,6 +122,8 @@ impl NavigationTarget {
106 focus_range: None, 122 focus_range: None,
107 kind: NAME, 123 kind: NAME,
108 container_name: None, 124 container_name: None,
125 description: description_inner(&node),
126 docs: docs_inner(&node),
109 } 127 }
110 } 128 }
111 129
@@ -290,83 +308,72 @@ impl NavigationTarget {
290 focus_range, 308 focus_range,
291 // ptr: Some(LocalSyntaxPtr::new(node)), 309 // ptr: Some(LocalSyntaxPtr::new(node)),
292 container_name: None, 310 container_name: None,
311 description: description_inner(node),
312 docs: docs_inner(node),
293 } 313 }
294 } 314 }
315}
295 316
296 pub(crate) fn node(&self, db: &RootDatabase) -> Option<TreeArc<SyntaxNode>> { 317fn docs_inner(node: &SyntaxNode) -> Option<String> {
297 let source_file = db.parse(self.file_id()).tree; 318 fn doc_comments<N: ast::DocCommentsOwner>(node: &N) -> Option<String> {
298 let source_file = source_file.syntax(); 319 node.doc_comment_text()
299 let node = source_file
300 .descendants()
301 .find(|node| node.kind() == self.kind() && node.range() == self.full_range())?
302 .to_owned();
303 Some(node)
304 }
305
306 pub(crate) fn docs(&self, db: &RootDatabase) -> Option<String> {
307 let node = self.node(db)?;
308 fn doc_comments<N: ast::DocCommentsOwner>(node: &N) -> Option<String> {
309 node.doc_comment_text()
310 }
311
312 visitor()
313 .visit(doc_comments::<ast::FnDef>)
314 .visit(doc_comments::<ast::StructDef>)
315 .visit(doc_comments::<ast::EnumDef>)
316 .visit(doc_comments::<ast::TraitDef>)
317 .visit(doc_comments::<ast::Module>)
318 .visit(doc_comments::<ast::TypeAliasDef>)
319 .visit(doc_comments::<ast::ConstDef>)
320 .visit(doc_comments::<ast::StaticDef>)
321 .visit(doc_comments::<ast::NamedFieldDef>)
322 .visit(doc_comments::<ast::EnumVariant>)
323 .visit(doc_comments::<ast::MacroCall>)
324 .accept(&node)?
325 } 320 }
326 321
327 /// Get a description of this node. 322 visitor()
328 /// 323 .visit(doc_comments::<ast::FnDef>)
329 /// e.g. `struct Name`, `enum Name`, `fn Name` 324 .visit(doc_comments::<ast::StructDef>)
330 pub(crate) fn description(&self, db: &RootDatabase) -> Option<String> { 325 .visit(doc_comments::<ast::EnumDef>)
331 // FIXME: After type inference is done, add type information to improve the output 326 .visit(doc_comments::<ast::TraitDef>)
332 let node = self.node(db)?; 327 .visit(doc_comments::<ast::Module>)
333 328 .visit(doc_comments::<ast::TypeAliasDef>)
334 fn visit_ascribed_node<T>(node: &T, prefix: &str) -> Option<String> 329 .visit(doc_comments::<ast::ConstDef>)
335 where 330 .visit(doc_comments::<ast::StaticDef>)
336 T: NameOwner + VisibilityOwner + TypeAscriptionOwner, 331 .visit(doc_comments::<ast::NamedFieldDef>)
337 { 332 .visit(doc_comments::<ast::EnumVariant>)
338 let mut string = visit_node(node, prefix)?; 333 .visit(doc_comments::<ast::MacroCall>)
339 334 .accept(&node)?
340 if let Some(type_ref) = node.ascribed_type() { 335}
341 string.push_str(": ");
342 type_ref.syntax().text().push_to(&mut string);
343 }
344 336
345 Some(string) 337/// Get a description of this node.
338///
339/// e.g. `struct Name`, `enum Name`, `fn Name`
340fn description_inner(node: &SyntaxNode) -> Option<String> {
341 // FIXME: After type inference is done, add type information to improve the output
342 fn visit_ascribed_node<T>(node: &T, prefix: &str) -> Option<String>
343 where
344 T: NameOwner + VisibilityOwner + TypeAscriptionOwner,
345 {
346 let mut string = visit_node(node, prefix)?;
347
348 if let Some(type_ref) = node.ascribed_type() {
349 string.push_str(": ");
350 type_ref.syntax().text().push_to(&mut string);
346 } 351 }
347 352
348 fn visit_node<T>(node: &T, label: &str) -> Option<String> 353 Some(string)
349 where 354 }
350 T: NameOwner + VisibilityOwner,
351 {
352 let mut string =
353 node.visibility().map(|v| format!("{} ", v.syntax().text())).unwrap_or_default();
354 string.push_str(label);
355 string.push_str(node.name()?.text().as_str());
356 Some(string)
357 }
358 355
359 visitor() 356 fn visit_node<T>(node: &T, label: &str) -> Option<String>
360 .visit(|node: &ast::FnDef| Some(crate::display::function_label(node))) 357 where
361 .visit(|node: &ast::StructDef| visit_node(node, "struct ")) 358 T: NameOwner + VisibilityOwner,
362 .visit(|node: &ast::EnumDef| visit_node(node, "enum ")) 359 {
363 .visit(|node: &ast::TraitDef| visit_node(node, "trait ")) 360 let mut string =
364 .visit(|node: &ast::Module| visit_node(node, "mod ")) 361 node.visibility().map(|v| format!("{} ", v.syntax().text())).unwrap_or_default();
365 .visit(|node: &ast::TypeAliasDef| visit_node(node, "type ")) 362 string.push_str(label);
366 .visit(|node: &ast::ConstDef| visit_ascribed_node(node, "const ")) 363 string.push_str(node.name()?.text().as_str());
367 .visit(|node: &ast::StaticDef| visit_ascribed_node(node, "static ")) 364 Some(string)
368 .visit(|node: &ast::NamedFieldDef| visit_ascribed_node(node, ""))
369 .visit(|node: &ast::EnumVariant| Some(node.name()?.text().to_string()))
370 .accept(&node)?
371 } 365 }
366
367 visitor()
368 .visit(|node: &ast::FnDef| Some(crate::display::function_label(node)))
369 .visit(|node: &ast::StructDef| visit_node(node, "struct "))
370 .visit(|node: &ast::EnumDef| visit_node(node, "enum "))
371 .visit(|node: &ast::TraitDef| visit_node(node, "trait "))
372 .visit(|node: &ast::Module| visit_node(node, "mod "))
373 .visit(|node: &ast::TypeAliasDef| visit_node(node, "type "))
374 .visit(|node: &ast::ConstDef| visit_ascribed_node(node, "const "))
375 .visit(|node: &ast::StaticDef| visit_ascribed_node(node, "static "))
376 .visit(|node: &ast::NamedFieldDef| visit_ascribed_node(node, ""))
377 .visit(|node: &ast::EnumVariant| Some(node.name()?.text().to_string()))
378 .accept(&node)?
372} 379}
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index e72b7a6e7..31b6679ae 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -72,7 +72,7 @@ pub(crate) fn reference_definition(
72 } 72 }
73 } 73 }
74 Some(Pat(pat)) => return Exact(NavigationTarget::from_pat(db, file_id, pat)), 74 Some(Pat(pat)) => return Exact(NavigationTarget::from_pat(db, file_id, pat)),
75 Some(SelfParam(par)) => return Exact(NavigationTarget::from_self_param(file_id, par)), 75 Some(SelfParam(par)) => return Exact(NavigationTarget::from_self_param(db, file_id, par)),
76 Some(GenericParam(_)) => { 76 Some(GenericParam(_)) => {
77 // FIXME: go to the generic param def 77 // FIXME: go to the generic param def
78 } 78 }
@@ -82,7 +82,7 @@ pub(crate) fn reference_definition(
82 // Fallback index based approach: 82 // Fallback index based approach:
83 let navs = crate::symbol_index::index_resolve(db, name_ref) 83 let navs = crate::symbol_index::index_resolve(db, name_ref)
84 .into_iter() 84 .into_iter()
85 .map(NavigationTarget::from_symbol) 85 .map(|s| NavigationTarget::from_symbol(db, s))
86 .collect(); 86 .collect();
87 Approximate(navs) 87 Approximate(navs)
88} 88}
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index f56965ef5..cb676eb12 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -86,13 +86,13 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
86 use crate::goto_definition::{ReferenceResult::*, reference_definition}; 86 use crate::goto_definition::{ReferenceResult::*, reference_definition};
87 let ref_result = reference_definition(db, position.file_id, name_ref); 87 let ref_result = reference_definition(db, position.file_id, name_ref);
88 match ref_result { 88 match ref_result {
89 Exact(nav) => res.extend(doc_text_for(db, nav)), 89 Exact(nav) => res.extend(doc_text_for(nav)),
90 Approximate(navs) => { 90 Approximate(navs) => {
91 // We are no longer exact 91 // We are no longer exact
92 res.exact = false; 92 res.exact = false;
93 93
94 for nav in navs { 94 for nav in navs {
95 res.extend(doc_text_for(db, nav)) 95 res.extend(doc_text_for(nav))
96 } 96 }
97 } 97 }
98 } 98 }
@@ -104,7 +104,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
104 104
105 if let Some(navs) = navs { 105 if let Some(navs) = navs {
106 for nav in navs { 106 for nav in navs {
107 res.extend(doc_text_for(db, nav)) 107 res.extend(doc_text_for(nav))
108 } 108 }
109 } 109 }
110 110
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs
index 2fe46cd13..dbebf50a6 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide_api/src/lib.rs
@@ -393,7 +393,7 @@ impl Analysis {
393 self.with_db(|db| { 393 self.with_db(|db| {
394 symbol_index::world_symbols(db, query) 394 symbol_index::world_symbols(db, query)
395 .into_iter() 395 .into_iter()
396 .map(NavigationTarget::from_symbol) 396 .map(|s| NavigationTarget::from_symbol(db, s))
397 .collect::<Vec<_>>() 397 .collect::<Vec<_>>()
398 }) 398 })
399 } 399 }