aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/docs.rs7
-rw-r--r--crates/ra_ide_api/src/call_info.rs3
-rw-r--r--crates/ra_ide_api/src/hover.rs7
-rw-r--r--crates/ra_syntax/src/ast.rs75
4 files changed, 65 insertions, 27 deletions
diff --git a/crates/ra_hir/src/docs.rs b/crates/ra_hir/src/docs.rs
index b1b47af9e..5db72c08a 100644
--- a/crates/ra_hir/src/docs.rs
+++ b/crates/ra_hir/src/docs.rs
@@ -27,10 +27,5 @@ pub trait Docs {
27} 27}
28 28
29pub(crate) fn docs_from_ast(node: &impl ast::DocCommentsOwner) -> Option<Documentation> { 29pub(crate) fn docs_from_ast(node: &impl ast::DocCommentsOwner) -> Option<Documentation> {
30 let comments = node.doc_comment_text(); 30 node.doc_comment_text().map(|it| Documentation::new(&it))
31 if comments.is_empty() {
32 None
33 } else {
34 Some(Documentation::new(&comments))
35 }
36} 31}
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs
index f203a6bf1..ee1e13799 100644
--- a/crates/ra_ide_api/src/call_info.rs
+++ b/crates/ra_ide_api/src/call_info.rs
@@ -126,8 +126,7 @@ impl CallInfo {
126 }; 126 };
127 127
128 let mut doc = None; 128 let mut doc = None;
129 let docs = node.doc_comment_text(); 129 if let Some(docs) = node.doc_comment_text() {
130 if !docs.is_empty() {
131 // Massage markdown 130 // Massage markdown
132 let mut processed_lines = Vec::new(); 131 let mut processed_lines = Vec::new();
133 let mut in_code_block = false; 132 let mut in_code_block = false;
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index ff9ae2d9c..f993a461c 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -100,12 +100,7 @@ impl NavigationTarget {
100 fn docs(&self, db: &RootDatabase) -> Option<String> { 100 fn docs(&self, db: &RootDatabase) -> Option<String> {
101 let node = self.node(db)?; 101 let node = self.node(db)?;
102 fn doc_comments<N: ast::DocCommentsOwner>(node: &N) -> Option<String> { 102 fn doc_comments<N: ast::DocCommentsOwner>(node: &N) -> Option<String> {
103 let comments = node.doc_comment_text(); 103 node.doc_comment_text()
104 if comments.is_empty() {
105 None
106 } else {
107 Some(comments)
108 }
109 } 104 }
110 105
111 visitor() 106 visitor()
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index ab3dd1b84..3d22a88f3 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -115,21 +115,38 @@ pub trait DocCommentsOwner: AstNode {
115 } 115 }
116 116
117 /// Returns the textual content of a doc comment block as a single string. 117 /// Returns the textual content of a doc comment block as a single string.
118 /// That is, strips leading `///` and joins lines 118 /// That is, strips leading `///` (+ optional 1 character of whitespace)
119 fn doc_comment_text(&self) -> std::string::String { 119 /// and joins lines.
120 self.doc_comments() 120 fn doc_comment_text(&self) -> Option<std::string::String> {
121 let docs = self
122 .doc_comments()
121 .filter(|comment| comment.is_doc_comment()) 123 .filter(|comment| comment.is_doc_comment())
122 .map(|comment| { 124 .map(|comment| {
123 let prefix = comment.prefix(); 125 let prefix_len = comment.prefix().len();
124 let trimmed = comment 126
125 .text() 127 let line = comment.text().as_str();
126 .as_str() 128
127 .trim() 129 // Determine if the prefix or prefix + 1 char is stripped
128 .trim_start_matches(prefix) 130 let pos = if line
129 .trim_start(); 131 .chars()
130 trimmed.to_owned() 132 .nth(prefix_len)
133 .map(|c| c.is_whitespace())
134 .unwrap_or(false)
135 {
136 prefix_len + 1
137 } else {
138 prefix_len
139 };
140
141 line[pos..].to_owned()
131 }) 142 })
132 .join("\n") 143 .join("\n");
144
145 if docs.is_empty() {
146 None
147 } else {
148 Some(docs)
149 }
133 } 150 }
134} 151}
135 152
@@ -704,6 +721,18 @@ impl BindPat {
704} 721}
705 722
706#[test] 723#[test]
724fn test_doc_comment_none() {
725 let file = SourceFile::parse(
726 r#"
727 // non-doc
728 mod foo {}
729 "#,
730 );
731 let module = file.syntax().descendants().find_map(Module::cast).unwrap();
732 assert!(module.doc_comment_text().is_none());
733}
734
735#[test]
707fn test_doc_comment_of_items() { 736fn test_doc_comment_of_items() {
708 let file = SourceFile::parse( 737 let file = SourceFile::parse(
709 r#" 738 r#"
@@ -713,5 +742,25 @@ fn test_doc_comment_of_items() {
713 "#, 742 "#,
714 ); 743 );
715 let module = file.syntax().descendants().find_map(Module::cast).unwrap(); 744 let module = file.syntax().descendants().find_map(Module::cast).unwrap();
716 assert_eq!("doc", module.doc_comment_text()); 745 assert_eq!("doc", module.doc_comment_text().unwrap());
746}
747
748#[test]
749fn test_doc_comment_preserves_indents() {
750 let file = SourceFile::parse(
751 r#"
752 /// doc1
753 /// ```
754 /// fn foo() {
755 /// // ...
756 /// }
757 /// ```
758 mod foo {}
759 "#,
760 );
761 let module = file.syntax().descendants().find_map(Module::cast).unwrap();
762 assert_eq!(
763 "doc1\n```\nfn foo() {\n // ...\n}\n```",
764 module.doc_comment_text().unwrap()
765 );
717} 766}