diff options
Diffstat (limited to 'crates/ra_analysis/src/descriptors')
-rw-r--r-- | crates/ra_analysis/src/descriptors/function/mod.rs | 60 |
1 files changed, 57 insertions, 3 deletions
diff --git a/crates/ra_analysis/src/descriptors/function/mod.rs b/crates/ra_analysis/src/descriptors/function/mod.rs index bb68b0ce7..ae40f3e8f 100644 --- a/crates/ra_analysis/src/descriptors/function/mod.rs +++ b/crates/ra_analysis/src/descriptors/function/mod.rs | |||
@@ -1,8 +1,11 @@ | |||
1 | pub(super) mod imp; | 1 | pub(super) mod imp; |
2 | mod scope; | 2 | mod scope; |
3 | 3 | ||
4 | use std::cmp::{min, max}; | ||
5 | |||
4 | use ra_syntax::{ | 6 | use ra_syntax::{ |
5 | ast::{self, AstNode, NameOwner} | 7 | ast::{self, AstNode, DocCommentsOwner, NameOwner}, |
8 | TextRange, TextUnit | ||
6 | }; | 9 | }; |
7 | 10 | ||
8 | use crate::{ | 11 | use crate::{ |
@@ -30,14 +33,17 @@ pub struct FnDescriptor { | |||
30 | pub label: String, | 33 | pub label: String, |
31 | pub ret_type: Option<String>, | 34 | pub ret_type: Option<String>, |
32 | pub params: Vec<String>, | 35 | pub params: Vec<String>, |
36 | pub doc: Option<String> | ||
33 | } | 37 | } |
34 | 38 | ||
35 | impl FnDescriptor { | 39 | impl FnDescriptor { |
36 | pub fn new(node: ast::FnDef) -> Option<Self> { | 40 | pub fn new(node: ast::FnDef) -> Option<Self> { |
37 | let name = node.name()?.text().to_string(); | 41 | let name = node.name()?.text().to_string(); |
38 | 42 | ||
43 | let mut doc = None; | ||
44 | |||
39 | // Strip the body out for the label. | 45 | // Strip the body out for the label. |
40 | let label: String = if let Some(body) = node.body() { | 46 | let mut label: String = if let Some(body) = node.body() { |
41 | let body_range = body.syntax().range(); | 47 | let body_range = body.syntax().range(); |
42 | let label: String = node | 48 | let label: String = node |
43 | .syntax() | 49 | .syntax() |
@@ -50,6 +56,36 @@ impl FnDescriptor { | |||
50 | node.syntax().text().to_string() | 56 | node.syntax().text().to_string() |
51 | }; | 57 | }; |
52 | 58 | ||
59 | if let Some((comment_range, docs)) = FnDescriptor::extract_doc_comments(node) { | ||
60 | let comment_range = comment_range.checked_sub(node.syntax().range().start()).unwrap(); | ||
61 | let start = comment_range.start().to_usize(); | ||
62 | let end = comment_range.end().to_usize(); | ||
63 | |||
64 | // Remove the comment from the label | ||
65 | label.replace_range(start..end, ""); | ||
66 | |||
67 | // Massage markdown | ||
68 | let mut processed_lines = Vec::new(); | ||
69 | let mut in_code_block = false; | ||
70 | for line in docs.lines() { | ||
71 | if line.starts_with("```") { | ||
72 | in_code_block = !in_code_block; | ||
73 | } | ||
74 | |||
75 | let line = if in_code_block && line.starts_with("```") && !line.contains("rust") { | ||
76 | "```rust".into() | ||
77 | } else { | ||
78 | line.to_string() | ||
79 | }; | ||
80 | |||
81 | processed_lines.push(line); | ||
82 | } | ||
83 | |||
84 | if !processed_lines.is_empty() { | ||
85 | doc = Some(processed_lines.join("\n")); | ||
86 | } | ||
87 | } | ||
88 | |||
53 | let params = FnDescriptor::param_list(node); | 89 | let params = FnDescriptor::param_list(node); |
54 | let ret_type = node.ret_type().map(|r| r.syntax().text().to_string()); | 90 | let ret_type = node.ret_type().map(|r| r.syntax().text().to_string()); |
55 | 91 | ||
@@ -57,10 +93,28 @@ impl FnDescriptor { | |||
57 | name, | 93 | name, |
58 | ret_type, | 94 | ret_type, |
59 | params, | 95 | params, |
60 | label, | 96 | label: label.trim().to_owned(), |
97 | doc | ||
61 | }) | 98 | }) |
62 | } | 99 | } |
63 | 100 | ||
101 | fn extract_doc_comments(node: ast::FnDef) -> Option<(TextRange, String)> { | ||
102 | if node.doc_comments().count() == 0 { | ||
103 | return None; | ||
104 | } | ||
105 | |||
106 | let comment_text = node.doc_comment_text(); | ||
107 | |||
108 | let (begin, end) = node.doc_comments() | ||
109 | .map(|comment| comment.syntax().range()) | ||
110 | .map(|range| (range.start().to_usize(), range.end().to_usize())) | ||
111 | .fold((std::usize::MAX, std::usize::MIN), |acc, range| (min(acc.0, range.0), max(acc.1, range.1))); | ||
112 | |||
113 | let range = TextRange::from_to(TextUnit::from_usize(begin), TextUnit::from_usize(end)); | ||
114 | |||
115 | Some((range, comment_text)) | ||
116 | } | ||
117 | |||
64 | fn param_list(node: ast::FnDef) -> Vec<String> { | 118 | fn param_list(node: ast::FnDef) -> Vec<String> { |
65 | let mut res = vec![]; | 119 | let mut res = vec![]; |
66 | if let Some(param_list) = node.param_list() { | 120 | if let Some(param_list) = node.param_list() { |