diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_analysis/src/hover.rs | 111 | ||||
-rw-r--r-- | crates/ra_analysis/src/imp.rs | 104 | ||||
-rw-r--r-- | crates/ra_analysis/src/lib.rs | 4 |
3 files changed, 110 insertions, 109 deletions
diff --git a/crates/ra_analysis/src/hover.rs b/crates/ra_analysis/src/hover.rs index c3825f6ea..c99d87da6 100644 --- a/crates/ra_analysis/src/hover.rs +++ b/crates/ra_analysis/src/hover.rs | |||
@@ -1,7 +1,11 @@ | |||
1 | use ra_db::{Cancelable, SyntaxDatabase}; | 1 | use ra_db::{Cancelable, SyntaxDatabase}; |
2 | use ra_syntax::{ast, AstNode}; | 2 | use ra_syntax::{ |
3 | AstNode, SyntaxNode, | ||
4 | ast::{self, NameOwner}, | ||
5 | algo::visit::{visitor, Visitor}, | ||
6 | }; | ||
3 | 7 | ||
4 | use crate::{db::RootDatabase, RangeInfo, FilePosition, FileRange}; | 8 | use crate::{db::RootDatabase, RangeInfo, FilePosition, FileRange, NavigationTarget}; |
5 | 9 | ||
6 | pub(crate) fn hover( | 10 | pub(crate) fn hover( |
7 | db: &RootDatabase, | 11 | db: &RootDatabase, |
@@ -10,7 +14,7 @@ pub(crate) fn hover( | |||
10 | let mut res = Vec::new(); | 14 | let mut res = Vec::new(); |
11 | let range = if let Some(rr) = db.approximately_resolve_symbol(position)? { | 15 | let range = if let Some(rr) = db.approximately_resolve_symbol(position)? { |
12 | for nav in rr.resolves_to { | 16 | for nav in rr.resolves_to { |
13 | res.extend(db.doc_text_for(nav)?) | 17 | res.extend(doc_text_for(db, nav)?) |
14 | } | 18 | } |
15 | rr.reference_range | 19 | rr.reference_range |
16 | } else { | 20 | } else { |
@@ -33,6 +37,107 @@ pub(crate) fn hover( | |||
33 | Ok(Some(res)) | 37 | Ok(Some(res)) |
34 | } | 38 | } |
35 | 39 | ||
40 | // FIXME: this should not really use navigation target. Rather, approximatelly | ||
41 | // resovled symbol should return a `DefId`. | ||
42 | fn doc_text_for(db: &RootDatabase, nav: NavigationTarget) -> Cancelable<Option<String>> { | ||
43 | let result = match (nav.description(db), nav.docs(db)) { | ||
44 | (Some(desc), Some(docs)) => Some("```rust\n".to_string() + &*desc + "\n```\n\n" + &*docs), | ||
45 | (Some(desc), None) => Some("```rust\n".to_string() + &*desc + "\n```"), | ||
46 | (None, Some(docs)) => Some(docs), | ||
47 | _ => None, | ||
48 | }; | ||
49 | |||
50 | Ok(result) | ||
51 | } | ||
52 | |||
53 | impl NavigationTarget { | ||
54 | fn node(&self, db: &RootDatabase) -> Option<SyntaxNode> { | ||
55 | let source_file = db.source_file(self.file_id); | ||
56 | let source_file = source_file.syntax(); | ||
57 | let node = source_file | ||
58 | .descendants() | ||
59 | .find(|node| node.kind() == self.kind && node.range() == self.range)? | ||
60 | .owned(); | ||
61 | Some(node) | ||
62 | } | ||
63 | |||
64 | fn docs(&self, db: &RootDatabase) -> Option<String> { | ||
65 | let node = self.node(db)?; | ||
66 | let node = node.borrowed(); | ||
67 | fn doc_comments<'a, N: ast::DocCommentsOwner<'a>>(node: N) -> Option<String> { | ||
68 | let comments = node.doc_comment_text(); | ||
69 | if comments.is_empty() { | ||
70 | None | ||
71 | } else { | ||
72 | Some(comments) | ||
73 | } | ||
74 | } | ||
75 | |||
76 | visitor() | ||
77 | .visit(doc_comments::<ast::FnDef>) | ||
78 | .visit(doc_comments::<ast::StructDef>) | ||
79 | .visit(doc_comments::<ast::EnumDef>) | ||
80 | .visit(doc_comments::<ast::TraitDef>) | ||
81 | .visit(doc_comments::<ast::Module>) | ||
82 | .visit(doc_comments::<ast::TypeDef>) | ||
83 | .visit(doc_comments::<ast::ConstDef>) | ||
84 | .visit(doc_comments::<ast::StaticDef>) | ||
85 | .accept(node)? | ||
86 | } | ||
87 | |||
88 | /// Get a description of this node. | ||
89 | /// | ||
90 | /// e.g. `struct Name`, `enum Name`, `fn Name` | ||
91 | fn description(&self, db: &RootDatabase) -> Option<String> { | ||
92 | // TODO: After type inference is done, add type information to improve the output | ||
93 | let node = self.node(db)?; | ||
94 | let node = node.borrowed(); | ||
95 | // TODO: Refactor to be have less repetition | ||
96 | visitor() | ||
97 | .visit(|node: ast::FnDef| { | ||
98 | let mut string = "fn ".to_string(); | ||
99 | node.name()?.syntax().text().push_to(&mut string); | ||
100 | Some(string) | ||
101 | }) | ||
102 | .visit(|node: ast::StructDef| { | ||
103 | let mut string = "struct ".to_string(); | ||
104 | node.name()?.syntax().text().push_to(&mut string); | ||
105 | Some(string) | ||
106 | }) | ||
107 | .visit(|node: ast::EnumDef| { | ||
108 | let mut string = "enum ".to_string(); | ||
109 | node.name()?.syntax().text().push_to(&mut string); | ||
110 | Some(string) | ||
111 | }) | ||
112 | .visit(|node: ast::TraitDef| { | ||
113 | let mut string = "trait ".to_string(); | ||
114 | node.name()?.syntax().text().push_to(&mut string); | ||
115 | Some(string) | ||
116 | }) | ||
117 | .visit(|node: ast::Module| { | ||
118 | let mut string = "mod ".to_string(); | ||
119 | node.name()?.syntax().text().push_to(&mut string); | ||
120 | Some(string) | ||
121 | }) | ||
122 | .visit(|node: ast::TypeDef| { | ||
123 | let mut string = "type ".to_string(); | ||
124 | node.name()?.syntax().text().push_to(&mut string); | ||
125 | Some(string) | ||
126 | }) | ||
127 | .visit(|node: ast::ConstDef| { | ||
128 | let mut string = "const ".to_string(); | ||
129 | node.name()?.syntax().text().push_to(&mut string); | ||
130 | Some(string) | ||
131 | }) | ||
132 | .visit(|node: ast::StaticDef| { | ||
133 | let mut string = "static ".to_string(); | ||
134 | node.name()?.syntax().text().push_to(&mut string); | ||
135 | Some(string) | ||
136 | }) | ||
137 | .accept(node)? | ||
138 | } | ||
139 | } | ||
140 | |||
36 | #[cfg(test)] | 141 | #[cfg(test)] |
37 | mod tests { | 142 | mod tests { |
38 | use ra_syntax::TextRange; | 143 | use ra_syntax::TextRange; |
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index eae73c2c4..1e9129c4f 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs | |||
@@ -8,11 +8,11 @@ use hir::{ | |||
8 | use ra_db::{FilesDatabase, SourceRoot, SourceRootId, SyntaxDatabase}; | 8 | use ra_db::{FilesDatabase, SourceRoot, SourceRootId, SyntaxDatabase}; |
9 | use ra_editor::{self, find_node_at_offset, assists, LocalEdit, Severity}; | 9 | use ra_editor::{self, find_node_at_offset, assists, LocalEdit, Severity}; |
10 | use ra_syntax::{ | 10 | use ra_syntax::{ |
11 | algo::{find_covering_node, visit::{visitor, Visitor}}, | 11 | algo::find_covering_node, |
12 | ast::{self, ArgListOwner, Expr, FnDef, NameOwner}, | 12 | ast::{self, ArgListOwner, Expr, FnDef, NameOwner}, |
13 | AstNode, SourceFileNode, | 13 | AstNode, SourceFileNode, |
14 | SyntaxKind::*, | 14 | SyntaxKind::*, |
15 | SyntaxNode, SyntaxNodeRef, TextRange, TextUnit, | 15 | SyntaxNodeRef, TextRange, TextUnit, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | use crate::{ | 18 | use crate::{ |
@@ -256,18 +256,6 @@ impl db::RootDatabase { | |||
256 | Ok(Some((binding, descr))) | 256 | Ok(Some((binding, descr))) |
257 | } | 257 | } |
258 | } | 258 | } |
259 | pub(crate) fn doc_text_for(&self, nav: NavigationTarget) -> Cancelable<Option<String>> { | ||
260 | let result = match (nav.description(self), nav.docs(self)) { | ||
261 | (Some(desc), Some(docs)) => { | ||
262 | Some("```rust\n".to_string() + &*desc + "\n```\n\n" + &*docs) | ||
263 | } | ||
264 | (Some(desc), None) => Some("```rust\n".to_string() + &*desc + "\n```"), | ||
265 | (None, Some(docs)) => Some(docs), | ||
266 | _ => None, | ||
267 | }; | ||
268 | |||
269 | Ok(result) | ||
270 | } | ||
271 | 259 | ||
272 | pub(crate) fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { | 260 | pub(crate) fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { |
273 | let syntax = self.source_file(file_id); | 261 | let syntax = self.source_file(file_id); |
@@ -506,91 +494,3 @@ impl<'a> FnCallNode<'a> { | |||
506 | } | 494 | } |
507 | } | 495 | } |
508 | } | 496 | } |
509 | |||
510 | impl NavigationTarget { | ||
511 | fn node(&self, db: &db::RootDatabase) -> Option<SyntaxNode> { | ||
512 | let source_file = db.source_file(self.file_id); | ||
513 | let source_file = source_file.syntax(); | ||
514 | let node = source_file | ||
515 | .descendants() | ||
516 | .find(|node| node.kind() == self.kind && node.range() == self.range)? | ||
517 | .owned(); | ||
518 | Some(node) | ||
519 | } | ||
520 | |||
521 | fn docs(&self, db: &db::RootDatabase) -> Option<String> { | ||
522 | let node = self.node(db)?; | ||
523 | let node = node.borrowed(); | ||
524 | fn doc_comments<'a, N: ast::DocCommentsOwner<'a>>(node: N) -> Option<String> { | ||
525 | let comments = node.doc_comment_text(); | ||
526 | if comments.is_empty() { | ||
527 | None | ||
528 | } else { | ||
529 | Some(comments) | ||
530 | } | ||
531 | } | ||
532 | |||
533 | visitor() | ||
534 | .visit(doc_comments::<ast::FnDef>) | ||
535 | .visit(doc_comments::<ast::StructDef>) | ||
536 | .visit(doc_comments::<ast::EnumDef>) | ||
537 | .visit(doc_comments::<ast::TraitDef>) | ||
538 | .visit(doc_comments::<ast::Module>) | ||
539 | .visit(doc_comments::<ast::TypeDef>) | ||
540 | .visit(doc_comments::<ast::ConstDef>) | ||
541 | .visit(doc_comments::<ast::StaticDef>) | ||
542 | .accept(node)? | ||
543 | } | ||
544 | |||
545 | /// Get a description of this node. | ||
546 | /// | ||
547 | /// e.g. `struct Name`, `enum Name`, `fn Name` | ||
548 | fn description(&self, db: &db::RootDatabase) -> Option<String> { | ||
549 | // TODO: After type inference is done, add type information to improve the output | ||
550 | let node = self.node(db)?; | ||
551 | let node = node.borrowed(); | ||
552 | // TODO: Refactor to be have less repetition | ||
553 | visitor() | ||
554 | .visit(|node: ast::FnDef| { | ||
555 | let mut string = "fn ".to_string(); | ||
556 | node.name()?.syntax().text().push_to(&mut string); | ||
557 | Some(string) | ||
558 | }) | ||
559 | .visit(|node: ast::StructDef| { | ||
560 | let mut string = "struct ".to_string(); | ||
561 | node.name()?.syntax().text().push_to(&mut string); | ||
562 | Some(string) | ||
563 | }) | ||
564 | .visit(|node: ast::EnumDef| { | ||
565 | let mut string = "enum ".to_string(); | ||
566 | node.name()?.syntax().text().push_to(&mut string); | ||
567 | Some(string) | ||
568 | }) | ||
569 | .visit(|node: ast::TraitDef| { | ||
570 | let mut string = "trait ".to_string(); | ||
571 | node.name()?.syntax().text().push_to(&mut string); | ||
572 | Some(string) | ||
573 | }) | ||
574 | .visit(|node: ast::Module| { | ||
575 | let mut string = "mod ".to_string(); | ||
576 | node.name()?.syntax().text().push_to(&mut string); | ||
577 | Some(string) | ||
578 | }) | ||
579 | .visit(|node: ast::TypeDef| { | ||
580 | let mut string = "type ".to_string(); | ||
581 | node.name()?.syntax().text().push_to(&mut string); | ||
582 | Some(string) | ||
583 | }) | ||
584 | .visit(|node: ast::ConstDef| { | ||
585 | let mut string = "const ".to_string(); | ||
586 | node.name()?.syntax().text().push_to(&mut string); | ||
587 | Some(string) | ||
588 | }) | ||
589 | .visit(|node: ast::StaticDef| { | ||
590 | let mut string = "static ".to_string(); | ||
591 | node.name()?.syntax().text().push_to(&mut string); | ||
592 | Some(string) | ||
593 | }) | ||
594 | .accept(node)? | ||
595 | } | ||
596 | } | ||
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 1904ff884..0e32a15f8 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs | |||
@@ -403,10 +403,6 @@ impl Analysis { | |||
403 | pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> { | 403 | pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> { |
404 | self.db.find_all_refs(position) | 404 | self.db.find_all_refs(position) |
405 | } | 405 | } |
406 | /// Returns documentation string for a given target. | ||
407 | pub fn doc_text_for(&self, nav: NavigationTarget) -> Cancelable<Option<String>> { | ||
408 | self.db.doc_text_for(nav) | ||
409 | } | ||
410 | /// Returns a short text descrbing element at position. | 406 | /// Returns a short text descrbing element at position. |
411 | pub fn hover(&self, position: FilePosition) -> Cancelable<Option<RangeInfo<String>>> { | 407 | pub fn hover(&self, position: FilePosition) -> Cancelable<Option<RangeInfo<String>>> { |
412 | hover::hover(&*self.db, position) | 408 | hover::hover(&*self.db, position) |